~ubuntu-branches/ubuntu/gutsy/diffutils/gutsy

« back to all changes in this revision

Viewing changes to src/side.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2005-02-15 22:45:18 UTC
  • Revision ID: james.westby@ubuntu.com-20050215224518-dw9ti3me00twpcmt
Tags: upstream-2.8.1
ImportĀ upstreamĀ versionĀ 2.8.1

Show diffs side-by-side

added added

removed removed

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