5 * Implements the highlighting of differences between old and new versions
13 #include "trueprint.h"
16 /* If there is no diff command just provide stubs */
18 void setup_diffs(void) { return; }
19 void init_diffs(char newfile
[]) { return; }
20 void end_diffs(void) { return; }
21 boolean
getdelline(long current_line
, char *input_line
, char_status input_status
[]) { return 0; }
22 boolean
line_inserted(long current_line
) { return 0; }
28 /* Ultrix needs these sys header files this way around */
29 #include <sys/types.h>
35 #include "trueprint.h"
45 static char *diffs_string
;
50 static unsigned short read_values(FILE *,long *value1_ptr
, long *value2_ptr
);
51 static boolean
read_long(FILE *, long *);
52 static void parse_line(void);
53 static stream_status
get_diff_char(char *input_char
, char_status
*status
);
55 static FILE *diffs_stream
;
56 static boolean diffs_on
;
57 static long diff_start_line
;
58 static long diff_end_line
;
59 static long lines_deleted
;
60 static long lines_added
;
73 string_option("O", "diff", NULL
, &diffs_string
, NULL
, NULL
,
75 "if <string> is a file then print diffs between <string> and input file\n"
76 " otherwise use as a prefix and print diffs");
83 * Initialises the diffs system:
84 * checks to see if any old version was provided and returns if not;
85 * calls end_diffs() if necessary;
86 * starts up the diff process;
89 init_diffs(char newfile
[])
92 char command
[COMMAND_LEN
];
95 /* Check to see if any old versions given */
97 if (diffs_string
== NULL
)
99 /* turn off diffs and return */
106 if ((diff_cmd
= getenv("TP_DIFF_CMD")) == NULL
)
112 * diffs_stream is only set if still reading from
113 * diff process, so need to finish the old diffs.
115 if (diffs_stream
!= NULL
) end_diffs();
118 * Check to see if diffs_string is a valid prefix or
121 sprintf(command
,"%s%s",diffs_string
,newfile
);
123 if (stat(command
,&dummy
) == 0)
125 sprintf(command
,"%s %s%s %s", diff_cmd
,diffs_string
,newfile
,newfile
);
128 else if (stat(diffs_string
,&dummy
) == 0)
130 sprintf(command
, "%s %s %s", diff_cmd
, diffs_string
, newfile
);
133 dm('d',3,"diffs command: %s\n",command
);
135 if ((diffs_stream
= fopenpipe(command
, "r")) == NULL
)
145 * scan a line reading one integer, and reading a second if the next
149 read_values(FILE *stream
, long *value1_ptr
, long *value2_ptr
)
153 unsigned short retval
;
158 /* read first value - if none then return*/
159 if (!read_long(stream
, value1_ptr
)) return 0;
161 /* skip spaces and check for a comma */
162 while ((next_char
= getc(stream
)) == ' ')
164 if (next_char
== ',')
166 /* if next char was a comma read second value */
167 if (!read_long(stream
, value2_ptr
))
169 fprintf(stderr
, gettext(CMD_NAME
": internal error reading diffs\n"));
172 /* and skip spaces again */
173 while ((next_char
= getc(stream
)) == ' ')
180 *value2_ptr
= *value1_ptr
;
183 if (next_char
!= EOF
)
185 /* replace last char in buffer for calling function */
186 ungetc((int)next_char
,stream
);
196 * Reads a long from a stream
199 read_long(FILE *stream
, long *value
)
202 boolean retval
= FALSE
;
209 if ((next_char
= getc(stream
)) == EOF
) break;
210 if (!isdigit(next_char
)) break;
213 *value
= (*value
* 10) + (next_char
- '0');
216 if (next_char
!= EOF
)
218 ungetc(next_char
, stream
);
228 * Reads a line from the diff stream, reading start and end line numbers
229 * for both the old and new files and the change type (d, a or c).
240 * Read the first two values - if there aren't any then we've
241 * reached the end of the file. These values refer to the
242 * first file so we're only interested in them for deleting lines.
244 if (read_values(diffs_stream
, &delete_start
, &delete_end
) == 0)
252 * Calculate the number of lines deleted.
253 * If delete start and delete end are the same then 1 line has been
254 * deleted... i.e. one more than the difference.
256 lines_deleted
= delete_end
- delete_start
+ 1;
258 diff_type
= getc(diffs_stream
); /* a=add, d=del, c=change */
267 fprintf(stderr
, gettext(CMD_NAME
": warning, bad diffs stream format char %c!\n"), diff_type
);
273 /* Same as before, only for new version of file */
274 if (read_values(diffs_stream
, &diff_start_line
, &diff_end_line
) == 0)
276 fprintf(stderr
, gettext(CMD_NAME
": warning, bad diffs stream format!\n"));
281 lines_added
= diff_end_line
- diff_start_line
+ 1;
283 if (diff_type
== 'a') lines_deleted
= 0;
284 if (diff_type
== 'd')
288 * deleted lines are actually *after* the specified line,
289 * so we need to pretend they're one line later...
291 diff_start_line
+= 1;
294 /* Skip to the end of the line */
295 while (getc(diffs_stream
) != '\n')
303 * Finish off the diffs system:
304 * - close the diffs stream (i.e. kill off the diff process);
311 if (!diffs_on
) return;
313 dm('d',3,"diffs: closing diffs\n");
315 fclosepipe(diffs_stream
);
323 * Simple function to be passed to getnextline() (which expands tabs, etc)
324 * in getdelline(), so we don't need to duplicate the functionality of
328 get_diff_char(char *input_char
, char_status
*status
)
331 *status
= CHAR_NORMAL
;
332 *input_char
= (char)getc(diffs_stream
);
341 * TRUE if a(nother) deleted line occurs after current line, returns
342 * line in parameters.
343 * FALSE if no deleted line between current line and next line.
347 getdelline(long current_line
, char *input_line
, char_status input_status
[])
353 * Check whether there is a deleted line waiting...
355 if ((current_line
!= diff_start_line
)
357 || (lines_deleted
== 0))
361 * First skip the first two characters of the line -
362 * they should be "< "
364 if ((getc(diffs_stream
)!='<') || (getc(diffs_stream
)!=' '))
366 fprintf(stderr
, gettext(CMD_NAME
": diffs stream in unexpected format\n"));
369 /* Read in the next line from diff stream */
370 getnextline(get_diff_char
,&blank_line
,input_line
,input_status
);
373 if (lines_deleted
== 0)
376 * If there are lines added then this is a "change" and
377 * the added lines will be dealt with by line_inserted().
378 * Otherwise we need to find the next difference with
381 if (lines_added
== 0)
384 /* else skip over line of ---- */
385 while (getc(diffs_stream
) != '\n')
396 * INSERT if line_number has been inserted
401 line_inserted(long current_line
)
404 boolean retval
= FALSE
;
405 if (!diffs_on
) return(FALSE
);
406 if ((current_line
>= diff_start_line
)
407 && (current_line
<= diff_end_line
))
410 while (getc(diffs_stream
) != '\n')
414 /* If reached the end of the insertion... */
415 if (current_line
>= diff_end_line
) parse_line();