source: trunk/third/diffutils/side.c @ 16149

Revision 16149, 6.8 KB checked in by rbasch, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16148, which included commits to RCS files with non-trunk default branches.
Line 
1/* sdiff-format output routines for GNU DIFF.
2   Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
3
4This file is part of GNU DIFF.
5
6GNU DIFF is distributed in the hope that it will be useful,
7but WITHOUT ANY WARRANTY.  No author or distributor
8accepts responsibility to anyone for the consequences of using it
9or for whether it serves any particular purpose or works at all,
10unless he says so in writing.  Refer to the GNU DIFF General Public
11License for full details.
12
13Everyone is granted permission to copy, modify and redistribute
14GNU DIFF, but only under the conditions described in the
15GNU DIFF General Public License.   A copy of this license is
16supposed to have been given to you along with GNU DIFF so you
17can know your rights and responsibilities.  It should be in a
18file named COPYING.  Among other things, the copyright notice
19and this notice must be preserved on all copies.  */
20
21
22#include "diff.h"
23
24static unsigned print_half_line PARAMS((char const * const *, unsigned, unsigned));
25static unsigned tab_from_to PARAMS((unsigned, unsigned));
26static void print_1sdiff_line PARAMS((char const * const *, int, char const * const *));
27static void print_sdiff_common_lines PARAMS((int, int));
28static void print_sdiff_hunk PARAMS((struct change *));
29
30/* Next line number to be printed in the two input files.  */
31static int next0, next1;
32
33/* Print the edit-script SCRIPT as a sdiff style output.  */
34
35void
36print_sdiff_script (script)
37     struct change *script;
38{
39  begin_output ();
40
41  next0 = next1 = - files[0].prefix_lines;
42  print_script (script, find_change, print_sdiff_hunk);
43
44  print_sdiff_common_lines (files[0].valid_lines, files[1].valid_lines);
45}
46
47/* Tab from column FROM to column TO, where FROM <= TO.  Yield TO.  */
48
49static unsigned
50tab_from_to (from, to)
51     unsigned from, to;
52{
53  FILE *out = outfile;
54  unsigned tab;
55
56  if (! tab_expand_flag)
57    for (tab = from + TAB_WIDTH - from % TAB_WIDTH;  tab <= to;  tab += TAB_WIDTH)
58      {
59        putc ('\t', out);
60        from = tab;
61      }
62  while (from++ < to)
63    putc (' ', out);
64  return to;
65}
66
67/*
68 * Print the text for half an sdiff line.  This means truncate to width
69 * observing tabs, and trim a trailing newline.  Returns the last column
70 * written (not the number of chars).
71 */
72static unsigned
73print_half_line (line, indent, out_bound)
74     char const * const *line;
75     unsigned indent, out_bound;
76{
77  FILE *out = outfile;
78  register unsigned in_position = 0, out_position = 0;
79  register char const
80        *text_pointer = line[0],
81        *text_limit = line[1];
82
83  while (text_pointer < text_limit)
84    {
85      register unsigned char c = *text_pointer++;
86
87      switch (c)
88        {
89        case '\t':
90          {
91            unsigned spaces = TAB_WIDTH - in_position % TAB_WIDTH;
92            if (in_position == out_position)
93              {
94                unsigned tabstop = out_position + spaces;
95                if (tab_expand_flag)
96                  {
97                    if (out_bound < tabstop)
98                      tabstop = out_bound;
99                    for (;  out_position < tabstop;  out_position++)
100                      putc (' ', out);
101                  }
102                else
103                  if (tabstop < out_bound)
104                    {
105                      out_position = tabstop;
106                      putc (c, out);
107                    }
108              }
109            in_position += spaces;
110          }
111          break;
112
113        case '\r':
114          {
115            putc (c, out);
116            tab_from_to (0, indent);
117            in_position = out_position = 0;
118          }
119          break;
120
121        case '\b':
122          if (in_position != 0 && --in_position < out_bound)
123            if (out_position <= in_position)
124              /* Add spaces to make up for suppressed tab past out_bound.  */
125              for (;  out_position < in_position;  out_position++)
126                putc (' ', out);
127            else
128              {
129                out_position = in_position;
130                putc (c, out);
131              }
132          break;
133
134        case '\f':
135        case '\v':
136        control_char:
137          if (in_position < out_bound)
138            putc (c, out);
139          break;
140
141        default:
142          if (! ISPRINT (c))
143            goto control_char;
144          /* falls through */
145        case ' ':
146          if (in_position++ < out_bound)
147            {
148              out_position = in_position;
149              putc (c, out);
150            }
151          break;
152
153        case '\n':
154          return out_position;
155        }
156    }
157
158  return out_position;
159}
160
161/*
162 * Print side by side lines with a separator in the middle.
163 * 0 parameters are taken to indicate white space text.
164 * Blank lines that can easily be caught are reduced to a single newline.
165 */
166
167static void
168print_1sdiff_line (left, sep, right)
169     char const * const *left;
170     int sep;
171     char const * const *right;
172{
173  FILE *out = outfile;
174  unsigned hw = sdiff_half_width, c2o = sdiff_column2_offset;
175  unsigned col = 0;
176  int put_newline = 0;
177
178  if (left)
179    {
180      if (left[1][-1] == '\n')
181        put_newline = 1;
182      col = print_half_line (left, 0, hw);
183    }
184
185  if (sep != ' ')
186    {
187      col = tab_from_to (col, (hw + c2o - 1) / 2) + 1;
188      if (sep == '|' && put_newline != (right[1][-1] == '\n'))
189        sep = put_newline ? '/' : '\\';
190      putc (sep, out);
191    }
192
193  if (right)
194    {
195      if (right[1][-1] == '\n')
196        put_newline = 1;
197      if (**right != '\n')
198        {
199          col = tab_from_to (col, c2o);
200          print_half_line (right, col, hw);
201        }
202    }
203
204  if (put_newline)
205    putc ('\n', out);
206}
207
208/* Print lines common to both files in side-by-side format.  */
209static void
210print_sdiff_common_lines (limit0, limit1)
211     int limit0, limit1;
212{
213  int i0 = next0, i1 = next1;
214
215  if (! sdiff_skip_common_lines  &&  (i0 != limit0 || i1 != limit1))
216    {
217      if (sdiff_help_sdiff)
218        fprintf (outfile, "i%d,%d\n", limit0 - i0, limit1 - i1);
219
220      if (! sdiff_left_only)
221        {
222          while (i0 != limit0 && i1 != limit1)
223            print_1sdiff_line (&files[0].linbuf[i0++], ' ', &files[1].linbuf[i1++]);
224          while (i1 != limit1)
225            print_1sdiff_line (0, ')', &files[1].linbuf[i1++]);
226        }
227      while (i0 != limit0)
228        print_1sdiff_line (&files[0].linbuf[i0++], '(', 0);
229    }
230
231  next0 = limit0;
232  next1 = limit1;
233}
234
235/* Print a hunk of an sdiff diff.
236   This is a contiguous portion of a complete edit script,
237   describing changes in consecutive lines.  */
238
239static void
240print_sdiff_hunk (hunk)
241     struct change *hunk;
242{
243  int first0, last0, first1, last1, deletes, inserts;
244  register int i, j;
245
246  /* Determine range of line numbers involved in each file.  */
247  analyze_hunk (hunk, &first0, &last0, &first1, &last1, &deletes, &inserts);
248  if (!deletes && !inserts)
249    return;
250
251  /* Print out lines up to this change.  */
252  print_sdiff_common_lines (first0, first1);
253
254  if (sdiff_help_sdiff)
255    fprintf (outfile, "c%d,%d\n", last0 - first0 + 1, last1 - first1 + 1);
256
257  /* Print ``xxx  |  xxx '' lines */
258  if (inserts && deletes)
259    {
260      for (i = first0, j = first1;  i <= last0 && j <= last1; ++i, ++j)
261        print_1sdiff_line (&files[0].linbuf[i], '|', &files[1].linbuf[j]);
262      deletes = i <= last0;
263      inserts = j <= last1;
264      next0 = first0 = i;
265      next1 = first1 = j;
266    }
267
268
269  /* Print ``     >  xxx '' lines */
270  if (inserts)
271    {
272      for (j = first1; j <= last1; ++j)
273        print_1sdiff_line (0, '>', &files[1].linbuf[j]);
274      next1 = j;
275    }
276
277  /* Print ``xxx  <     '' lines */
278  if (deletes)
279    {
280      for (i = first0; i <= last0; ++i)
281        print_1sdiff_line (&files[0].linbuf[i], '<', 0);
282      next0 = i;
283    }
284}
Note: See TracBrowser for help on using the repository browser.