File mgdiff-1.0.1.diff of Package mgdiff
--- mgdiff.c
+++ mgdiff.c
@@ -1,13 +1,14 @@
-#ifndef lint
+#if 0
static char rcsid[] = "mgdiff.c,v 2.1 1994/09/29 01:56:53 dan Exp";
#endif
-#ifndef lint
+#if 0
static char copyright[] = "Copyright (c) 1994, Daniel Williams";
#endif
/*
* Copyright (c) 1994 Daniel Williams
+ * Copyright (c) 2003 Erik de Castro Lopo
*
* The X Consortium, and any party obtaining a copy of these files from
* the X Consortium, directly or indirectly, is granted, free of charge,
@@ -40,6 +41,7 @@
#include <assert.h>
#include <errno.h>
#include <sys/stat.h>
+#include <locale.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
@@ -99,7 +101,7 @@
static void show_version (Widget parent);
static void update_overall (void);
static void refresh (void);
-static void toggle_saveas_sensitive (Boolean sensitive);
+static void toggle_saveas_sensitive (Boolean saveas, Boolean save_left, Boolean save_right);
static void exit_cb (Widget w, XtPointer closure, XtPointer call_data);
static void Select (Widget widget, XEvent *event, String *params, Cardinal *num_params);
static void Scroll (Widget widget, XEvent *event, String *params, Cardinal *num_params);
@@ -109,9 +111,14 @@
static void unselect_all (void);
static Boolean all_selected (void);
static Dimension get_preferred_width (Widget w);
-static char *basename (char *name);
+static char *mgdiff_basename (char *name);
-#define APP_DEFAULTS_VERSION 1
+enum {
+ WIDGET_LEFT = 0x10000000,
+ WIDGET_RIGHT = 0x20000000
+} ;
+
+#define APP_DEFAULTS_VERSION 2
/*
* treat failure to find the resources from the application defaults
@@ -120,10 +127,16 @@
*/
static String fallbacks[] = {
"*menubar.button_0.XmString: File",
- "*file_menu*button_4.XmString: Exit",
+ "*file_menu*button_6.XmString: Exit",
NULL
};
+static char unselected_text_msg [] =
+ "Unselected blocks remain.\n\n"
+ "Press Cancel to go back to correct this.\n"
+ "Pressing OK will save the merged data with all unselected\n"
+ "blocks absent from the output file." ;
+
static XrmOptionDescRec option_table[] = {
{"-quit", "quitIfSame", XrmoptionNoArg, "true"},
{"-args", "diffArgs", XrmoptionSepArg, NULL},
@@ -137,6 +150,7 @@
static struct screenstate {
Block *b;
+ Block *lastSelected;
int topline;
int leftcol;
int sindex, findex[2];
@@ -170,7 +184,7 @@
static char *str_fnamel, *str_fnamer;
static char *str_snamel, *str_snamer;
-static char *tempfname;
+static char tempfname [512] = "" ;
static char *user_filename;
char *progname;
@@ -195,8 +209,11 @@
* anyway) and less complex than turning on and correctly processing
* GraphicsExpose events.
*/
-static int statel = VisibilityFullyObscured;
-static int stater = VisibilityFullyObscured;
+
+/* Make the initial state unobscured. */
+static int statel = VisibilityUnobscured;
+static int stater = VisibilityUnobscured;
+
/* ARGSUSED1 */
static void Visible (Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
@@ -398,23 +415,37 @@
Region region;
Block *b;
GC fore, back;
- int columns;
-
+ int columns, widget_side;
+
+ Side x_selection = NEITHER;
+ Block *curr_x_block = newss.lastSelected;
+
+ if (curr_x_block) {
+ x_selection = curr_x_block->selected;
+ }
+
XtVaGetValues (w, XmNwidth, &width, XmNheight, &height, NULL);
XtAddExposureToRegion (cbs->event, region = XCreateRegion ());
columns = (int) width / font_width + 1;
+ if (w == textl)
+ widget_side = WIDGET_LEFT;
+ else if (w == textr)
+ widget_side = WIDGET_RIGHT;
+ else
+ assert (False);
+
itemp = newss.sindex;
ypos = 0;
for (b = newss.b; b != NULL; b = b->next) {
int j;
Chunk *ths, *oth;
- if (w == textl) {
+ if (widget_side == WIDGET_LEFT) {
ths = &b->arr[LEFT];
oth = &b->arr[RIGHT];
- if (b->selected == LEFT) {
+ if (b->selected == LEFT || b->selected == BOTH) {
fore = gcfore[4];
back = gcback[4];
}
@@ -423,10 +454,10 @@
back = gcback[ths->type];
}
}
- else if (w == textr) {
+ else if (widget_side == WIDGET_RIGHT) {
ths = &b->arr[RIGHT];
oth = &b->arr[LEFT];
- if (b->selected == RIGHT) {
+ if (b->selected == RIGHT || b->selected == BOTH) {
fore = gcfore[4];
back = gcback[4];
}
@@ -537,15 +568,32 @@
open_right_file (toplevel, str_fnamer);
break;
case 3: /* save as */
- if (all_selected ()) {
- set_cursor (toplevel);
- save_file (toplevel, di->first, str_fnamel);
+ if (all_selected () == False) {
+ if (modal_question (toplevel, "Mgdiff Save", unselected_text_msg) == False)
+ break;
}
- else {
- werror (toplevel, "Save Error", "Save", "there are unselected text blocks");
+ save_file (toplevel, di->first, str_fnamel);
+ break;
+ case 4: /* save as left */
+ if (all_selected () == False) {
+ if (modal_question (toplevel, "Mgdiff Save", unselected_text_msg) == False)
+ break;
}
+ set_cursor (toplevel);
+ save_as_filename (toplevel, di->first, str_fnamel);
+ reset_cursor (toplevel);
+ break;
+ case 5: /* save as right */
+ if (all_selected () == False) {
+ if (modal_question (toplevel, "Mgdiff Save", unselected_text_msg) == False)
+ break;
+ }
+ set_cursor (toplevel);
+ save_as_filename (toplevel, di->first, str_fnamer);
+ reset_cursor (toplevel);
+
break;
- case 4: /* exit */
+ case 6: /* exit */
exit_cb (w, NULL, NULL);
break;
default:
@@ -724,7 +772,6 @@
dagcb = XtGetGC (children[1], GCForeground|GCBackground, &gc_values);
been_here = 1;
}
-
for (i = 0; i < 3; i++) {
XtVaGetValues (children[i],
XmNwidth, &width[i],
@@ -755,7 +802,7 @@
yfpos[LEFT] += b->arr[LEFT].fsize;
h = ((int) height[0] * yfpos[LEFT] / max (di->flines[LEFT], 1)) - y;
y3 = ((h == 0) ? y1 : (y1 + h - 1));
- back = (b->selected == LEFT) ? 4 : b->arr[LEFT].type;
+ back = (b->selected == LEFT || b->selected == BOTH) ? 4 : b->arr[LEFT].type;
XFillRectangle (XtDisplay (children[0]), p[0], gcback[back],
0, y, width[0], h);
@@ -763,7 +810,7 @@
yfpos[RIGHT] += b->arr[RIGHT].fsize;
h = ((int) height[2] * yfpos[RIGHT] / max (di->flines[RIGHT], 1)) - y;
y4 = ((h == 0) ? y2 : (y2 + h - 1));
- back = (b->selected == RIGHT) ? 4 : b->arr[RIGHT].type;
+ back = (b->selected == RIGHT || b->selected == BOTH) ? 4 : b->arr[RIGHT].type;
XFillRectangle (XtDisplay (children[2]), p[2], gcback[back],
0, y, width[2], h);
@@ -906,6 +953,7 @@
*/
static char *foo3 = "\
<Btn1Down>: Select() \n\
+ <Btn2Down>: Select() \n\
~Ctrl <Key>osfPageDown: Scroll(PageDown) \n\
~Ctrl <Key>osfPageUp: Scroll(PageUp) \n\
<Key>osfLeft: Scroll(Left) \n\
@@ -951,8 +999,9 @@
*/
static void cleanup_at_exit (void)
{
- if (tempfname != NULL)
+ if (strlen (tempfname) > 0)
(void) unlink (tempfname);
+ tempfname [0] = 0 ;
}
/*
@@ -1018,8 +1067,11 @@
{"debug", "Debug", XtRBoolean, sizeof (Boolean), 0, XtRString, "false"},
{"filename", "Filename", XtRString, sizeof (String), 0, XtRString, ""}};
- progname = basename (argv[0]);
+ progname = mgdiff_basename (argv[0]);
+ XtSetLanguageProc (NULL, NULL, NULL);
+ setlocale (LC_ALL, "");
+ setlocale (LC_CTYPE, "en");
toplevel = XtVaAppInitialize (&app, "Mgdiff", option_table, XtNumber (option_table),
#if X11R5
&argc,
@@ -1079,7 +1131,6 @@
};
werror_long (toplevel, "Wrong Application Defaults", array, sizeof (array) / sizeof (array[0]));
}
-
if (debug_flag) {
XSetErrorHandler (x_error_handler);
XtAppSetErrorHandler (app, xt_error_handler);
@@ -1087,7 +1138,10 @@
else
XtAppSetWarningHandler (app, xt_warning_handler);
-#if sun
+#if 0
+ /* May possibly be required on some old versions of SunOS.
+ ** Definitely not required on Solaris.
+ */
(void) on_exit (cleanup_at_exit, NULL);
#else
(void) atexit (cleanup_at_exit);
@@ -1109,14 +1163,17 @@
* two filenames on command line; process them
*/
case 3:
+ if (strcmp (argv[1], "-") == 0 && strcmp (argv[2], "-") == 0) {
+ (void) fprintf (stderr, "Cannot use stdin for both file input\n");
+ exit (2);
+ }
if (strcmp (argv[1], "-") == 0) {
- tempfname = tempnam (NULL, "mgdif");
- str_fnamel = strdup (tempfname);
- str_snamel = strdup (user_filename);
- if (!copy_to_file (stdin, tempfname)) {
+ if (!copy_to_tempfile (stdin, tempfname, sizeof (tempfname))) {
(void) fprintf (stderr, "Error copying stdin to temp file \"%s\"\n", tempfname);
exit (2);
}
+ str_fnamel = strdup (tempfname);
+ str_snamel = strdup (user_filename);
}
else if (!file_tests (toplevel, argv[1])) {
no_files_flag = True;
@@ -1131,13 +1188,12 @@
}
if (strcmp (argv[2], "-") == 0) {
- tempfname = tempnam (NULL, "mgdif");
- str_fnamer = strdup (tempfname);
- str_snamer = strdup (user_filename);
- if (!copy_to_file (stdin, tempfname)) {
+ if (!copy_to_tempfile (stdin, tempfname, sizeof (tempfname))) {
(void) fprintf (stderr, "Error copying stdin to temp file \"%s\"\n", tempfname);
exit (2);
}
+ str_fnamer = strdup (tempfname);
+ str_snamer = strdup (user_filename);
}
else if (!file_tests (toplevel, argv[2])) {
no_files_flag = True;
@@ -1174,6 +1230,7 @@
}
newss.b = di->first;
+ newss.lastSelected= NULL;
newss.topline = newss.sindex = newss.findex[LEFT] = newss.findex[RIGHT] = 0;
mainw = XtVaCreateManagedWidget ("mainw", xmMainWindowWidgetClass,
@@ -1205,10 +1262,13 @@
XmVaPUSHBUTTON, NULL, NULL, NULL, NULL,
XmVaSEPARATOR,
XmVaPUSHBUTTON, NULL, NULL, NULL, NULL,
+ XmVaPUSHBUTTON, NULL, NULL, NULL, NULL,
+ XmVaSEPARATOR,
+ XmVaPUSHBUTTON, NULL, NULL, NULL, NULL,
NULL);
if (no_files_flag || (di->status == 2)) {
toggle_openlr_sensitive (False);
- toggle_saveas_sensitive (False);
+ toggle_saveas_sensitive (False, False, False);
}
XmVaCreateSimplePulldownMenu (menubar, "view_menu", 1, view_cb,
XmVaPUSHBUTTON, NULL, NULL, NULL, NULL,
@@ -1491,6 +1551,7 @@
XtAppMainLoop (app);
/* NOTREACHED */
+ return 0;
}
static void redraw_partial_vert (Widget w)
@@ -1622,9 +1683,9 @@
{
char buffer[16];
- (void) sprintf (buffer, "%*d", linenum_columns, l);
+ (void) snprintf (buffer, sizeof (buffer), "%*d", linenum_columns, l);
XmTextFieldSetString (linenuml, buffer);
- (void) sprintf (buffer, "%*d", linenum_columns, r);
+ (void) snprintf (buffer, sizeof (buffer), "%*d", linenum_columns, r);
XmTextFieldSetString (linenumr, buffer);
}
@@ -1986,7 +2047,7 @@
mgdiff_width, mgdiff_height,
fg, bg,
DefaultDepth (dpy, DefaultScreen (dpy)));
- (void) sprintf (buffer, "mgdiff\n\nA graphical difference browser\n\nAuthor: Dan Williams (dan@sass.com)\nVersion: %s PL%s", VERSION, PATCHLEVEL);
+ (void) snprintf (buffer, sizeof (buffer), "mgdiff\n\nA graphical difference browser\n\nAuthors: Dan Williams (dan@sass.com)\nErik de Castro Lopo (erikd@mega-nerd.com)\n\nVersion: %s PL%s", VERSION, PATCHLEVEL);
XtVaSetValues (dialog,
XmNautoUnmanage, True,
@@ -2041,12 +2102,12 @@
if (di->status != 2) {
no_files_flag = False;
toggle_openlr_sensitive (True);
- toggle_saveas_sensitive (True);
+ toggle_saveas_sensitive (True, True, True);
}
else {
no_files_flag = True;
toggle_openlr_sensitive (False);
- toggle_saveas_sensitive (False);
+ toggle_saveas_sensitive (False, False, False);
free (str_fnamel);
free (str_snamel);
free (str_fnamer);
@@ -2082,7 +2143,7 @@
if (di->status == 2) {
no_files_flag = True;
toggle_openlr_sensitive (False);
- toggle_saveas_sensitive (False);
+ toggle_saveas_sensitive (False, False, False);
free (str_fnamel);
free (str_snamel);
free (str_fnamer);
@@ -2117,7 +2178,7 @@
if (di->status == 2) {
no_files_flag = True;
toggle_openlr_sensitive (False);
- toggle_saveas_sensitive (False);
+ toggle_saveas_sensitive (False, False, False);
free (str_fnamel);
free (str_snamel);
free (str_fnamer);
@@ -2133,6 +2194,7 @@
handle_diff_errors (di);
}
+
static void refresh (void)
{
newss.b = di->first;
@@ -2182,9 +2244,11 @@
toggle_openlr_sensitive (sensitive);
}
-static void toggle_saveas_sensitive (Boolean sensitive)
+static void toggle_saveas_sensitive (Boolean saveas, Boolean save_left, Boolean save_right)
{
- XtSetSensitive (XtNameToWidget (file_menu, "button_3"), sensitive);
+ XtSetSensitive (XtNameToWidget (file_menu, "button_3"), saveas);
+ XtSetSensitive (XtNameToWidget (file_menu, "button_4"), save_left);
+ XtSetSensitive (XtNameToWidget (file_menu, "button_5"), save_right);
}
/*
@@ -2196,78 +2260,263 @@
exit ((di != NULL) ? di->status : 2);
}
+static void lost_selection ( Widget widget, Atom* selection) {
+
+ if (debug_flag) {
+ fprintf(stderr,"selection lost on widget %p\n",widget);
+ }
+// newss.lastSelected=NULL;
+}
+
+static Boolean do_selection(Widget widget, Atom* selection, Atom* target ,
+ Atom* type, XtPointer* value,
+ unsigned long* length,int* format) {
+
+ Atom targets = XInternAtom(XtDisplay(widget), "TARGETS", False);
+ Atom *array;
+ char* result;
+ char* line;
+ int i,j;
+ Block *b= newss.lastSelected;
+ Chunk *chunk =NULL;
+
+ if (debug_flag) {
+ fprintf(stderr,"selection request on widget %p\n",widget);
+ }
+
+ if (!b) return False;
+
+ chunk = &(b->arr[b->selected]);
+
+ if (*target == targets)
+ {
+ if (debug_flag) {
+ fprintf(stderr,"clipboards targets requested on widget %p\n",widget);
+ }
+ /*
+ * Handle request for data types
+ */
+
+ if ((array = (Atom *)XtMalloc((unsigned)(sizeof(Atom) * 1))) == NULL)
+ return False;
+ *value = (XtPointer)array;
+ array[0] = XA_STRING;
+ *type = XA_ATOM;
+ *format = sizeof(Atom) * 8;
+ *length = 5;
+ return True;
+ }
+
+ if (*target == XA_STRING) {
+ /*
+ * request for string data !.
+ */
+ if (debug_flag) {
+ fprintf(stderr,"string target requested on widget %p\n",widget);
+ }
+
+ /*
+ * Iterate through the lines in the text block
+ * summing the lengths
+ */
+ *length=0;
+ for (i = 0; i < chunk->fsize; i++) {
+ if ((chunk->wtext != NULL) && (chunk->wtext[i] != NULL)) {
+ *length += (strlen(chunk->wtext[i])+1);
+ } else {
+ *length += (strlen(chunk->text[i])+1);
+ }
+ }
+ *format = 8; /* 8 bits per char */
+ *type = XA_STRING;
+ if (debug_flag) {
+ fprintf(stderr,"string length= %li\n",*length);
+ }
+
+ *value = XtMalloc(*length);
+ result = (char*)(*value);
+ /*
+ * Iterate through the lines in the text block
+ * moving the data into the clipboard memblock
+ */
+ for (i = 0; i < chunk->fsize; i++) {
+ if ((chunk->wtext != NULL) && (chunk->wtext[i] != NULL)) {
+ line = chunk->wtext[i] ;
+ } else {
+ line = chunk->text[i];
+ }
+ j =strlen(line);
+ memcpy(result,line,j);
+ result+=j;
+ *(result++)= '\n';
+ }
+
+
+ if (debug_flag) {
+ fprintf(stderr,"all done string at= %p\n",*value);
+ }
+ if (!(*value)) {
+ return False;
+ }
+ return True;
+ }
+ /*
+ * Haven't found data type we know about!
+ */
+ return False;
+}
+
+
+
+
/* ARGSUSED2 */
static void Select (Widget widget, XEvent *event, String *params, Cardinal *num_params)
{
- if (event->xany.type == ButtonPress) {
+ /*
+ ** The original version of this function was rather confusing. It was
+ ** rewritten to make it easier to follow so that more selection features
+ ** could then be added (ie select both left and right).
+ ** The function itself and the main for loop are written so that evaluation
+ ** of current state occurs at the top and processing at the bottom. For
+ ** instance, the first test to see if the XEvent is a ButtonPress returns
+ ** from the function rather than making the whole function one huge if
+ ** statement. Similarly, continue statements are used in the for loop to
+ ** bypass the lower part of the loop.
+ */
Block *b;
Dimension ypos, height;
- int itemp, rect_height;
+ int itemp, rect_height, widget_side;
+ Side x_selection = NEITHER;
+ Block *curr_x_block = newss.lastSelected;
+
+ if (event->xany.type != ButtonPress)
+ return;
+
+ if (widget == textl)
+ widget_side = WIDGET_LEFT;
+ else if (widget == textr)
+ widget_side = WIDGET_RIGHT;
+ else
+ assert (False);
+
+
+ if (curr_x_block) {
+ x_selection = curr_x_block->selected;
+ }
XtVaGetValues (widget, XmNheight, &height, NULL);
itemp = newss.sindex;
ypos = 0;
+ //Find selected chunk!.
for (b = newss.b; b != NULL; b = b->next) {
+ /* If the current ypos is > height of window, we're done, so just return. */
+ if (ypos > height)
+ return;
+
if ((rect_height = font_height * (b->ssize - itemp)) > (int) height)
rect_height = height;
+ itemp = 0;
- if ((event->xbutton.y >= (unsigned int) ypos) &&
- (event->xbutton.y < (unsigned int) (ypos + rect_height)) &&
- (b->arr[LEFT].type != SAME)) {
- switch (b->selected) {
- case LEFT:
- if (widget == textl) {
- b->selected = NEITHER;
- redraw_partial (textl, ypos, rect_height);
- redraw_partial (textr, ypos, rect_height);
- update_pixmaps ();
+ if (event->xbutton.y < (unsigned int) ypos) {
+ ypos += rect_height;
+ continue;
}
- else if (widget == textr) {
- b->selected = RIGHT;
- redraw_partial (textl, ypos, rect_height);
- redraw_partial (textr, ypos, rect_height);
- update_pixmaps ();
+
+ if (event->xbutton.y >= (unsigned int) (ypos + rect_height)) {
+ ypos += rect_height;
+ continue;
}
- else
- assert (False);
- break;
- case RIGHT:
- if (widget == textl) {
+
+ /*
+ ** Have now found the selected block.
+ ** If the LH and RH sides of the selected block are the same, then
+ ** there is nothing to do, so just return.
+ */
+ if (b->arr[LEFT].type == SAME)
+ return;
+
+ /*
+ ** This state machine has been rewritten as a true state machine. The
+ ** original had three cases (LEFT< RIGHT, NEITHER) and an if statement
+ ** in each case. Since the original simplification, more states have
+ ** been added (ie select BOTH state).
+ */
+ switch (widget_side | (event->xbutton.button << 4) | b->selected) {
+ case WIDGET_LEFT | (1<<4) | NEITHER:
+ case WIDGET_LEFT | (1<<4) | RIGHT:
+ case WIDGET_LEFT | (1<<4) | BOTH:
b->selected = LEFT;
- redraw_partial (textl, ypos, rect_height);
- redraw_partial (textr, ypos, rect_height);
- update_pixmaps ();
- }
- else if (widget == textr) {
+ break;
+ case WIDGET_LEFT | (1<<4) | LEFT:
+ case WIDGET_RIGHT | (2<<4) | BOTH:
b->selected = NEITHER;
- redraw_partial (textl, ypos, rect_height);
- redraw_partial (textr, ypos, rect_height);
- update_pixmaps ();
- }
- else
- assert (False);
break;
- case NEITHER:
- b->selected = (widget == textl) ? LEFT : RIGHT;
- redraw_partial (textl, ypos, rect_height);
- redraw_partial (textr, ypos, rect_height);
- update_pixmaps ();
+
+ case WIDGET_RIGHT | (1<<4) | NEITHER:
+ case WIDGET_RIGHT | (1<<4) | LEFT:
+ case WIDGET_RIGHT | (1<<4) | BOTH:
+ b->selected = RIGHT;
+ break;
+ case WIDGET_RIGHT | (1<<4) | RIGHT:
+ case WIDGET_LEFT | (2<<4) | BOTH:
+ b->selected = NEITHER;
break;
- default:
- assert (False);
+
+ case WIDGET_LEFT | (2<<4) | NEITHER:
+ case WIDGET_LEFT | (2<<4) | LEFT:
+ case WIDGET_LEFT | (2<<4) | RIGHT:
+ if (b->arr[LEFT].type == DIFF) {
+ b->selected = BOTH;
break;
}
- return;
- }
+ if (b->arr[LEFT].wtext != NULL)
+ b->selected = (b->selected == LEFT) ? NEITHER : LEFT;
+ break ;
+
+ case WIDGET_RIGHT | (2<<4) | NEITHER:
+ case WIDGET_RIGHT | (2<<4) | LEFT:
+ case WIDGET_RIGHT | (2<<4) | RIGHT:
+ if (b->arr[LEFT].type == DIFF) {
+ b->selected = BOTH;
+ break;
+ }
+ if (b->arr[RIGHT].wtext != NULL)
+ b->selected = (b->selected == RIGHT) ? NEITHER : RIGHT;
+ break ;
- ypos += rect_height;
- itemp = 0;
- if (ypos > height)
- return;
+ default:
+ printf ("Button:%d widget:%s sel:%d\n", event->xbutton.button,
+ widget_side == WIDGET_LEFT ? "LEFT" : "RIGHT", b->selected) ;
+ assert (False);
+ break;
+ }
+ redraw_partial (textl, ypos, rect_height);
+ redraw_partial (textr, ypos, rect_height);
+ update_pixmaps ();
+
+ if ( b->selected == NEITHER ) {
+ if (b == newss.lastSelected)
+ newss.lastSelected=NULL;
+ } else {
+ newss.lastSelected=b;
}
- }
+
+ if ( !newss.lastSelected
+ || (x_selection != newss.lastSelected->selected)
+ // || (newss.lastSelected != curr_x_block )
+ )
+ {
+ XtDisownSelection(widget,XA_PRIMARY, CurrentTime);
+ }
+
+ if (newss.lastSelected) {
+ XtOwnSelection(widget,XA_PRIMARY, CurrentTime,&do_selection,&lost_selection,NULL);
+ }
+
+ return;
+ }
}
/*
@@ -2307,14 +2556,14 @@
else {
char buffer[1024];
- (void) sprintf (buffer, "Illegal argument to action proc Scroll (\"%s\")", params[0]);
+ (void) snprintf (buffer, sizeof (buffer), "Illegal argument to action proc Scroll (\"%s\")", params[0]);
XtAppWarning (XtWidgetToApplicationContext (widget), buffer);
}
}
else {
char buffer[1024];
- (void) sprintf (buffer, "Illegal number of arguments to action proc Scroll (\"%d\")", *num_params);
+ (void) snprintf (buffer, sizeof (buffer), "Illegal number of arguments to action proc Scroll (\"%d\")", *num_params);
XtAppWarning (XtWidgetToApplicationContext (widget), buffer);
}
}
@@ -2391,7 +2640,7 @@
/*
* delete any prefix ending in '/' and return a copy
*/
-static char *basename (char *path)
+static char *mgdiff_basename (char *path)
{
if (path) {
char *p;
--- mgdiff.h
+++ mgdiff.h
@@ -1,7 +1,7 @@
#ifndef MXDIFF_H
#define MXDIFF_H
-#ifndef lint
+#if 0
static char rcsid_mgdiff_h[] = "mgdiff.h,v 2.0 1994/05/19 02:01:15 dan Exp";
#endif
@@ -52,7 +52,11 @@
short *tlen; /* the lengths of each line */
} Chunk;
-typedef enum {LEFT = 0, RIGHT, NEITHER} Side;
+/*
+** LEFT and RIGHT must be 0 and 1 respectively as they are used
+** to index as array.
+*/
+typedef enum {LEFT = 0, RIGHT, NEITHER, BOTH} Side;
/*
* a block is an element of a doubly linked list containing a left chunk
@@ -86,4 +90,11 @@
*/
#define X11R5 (defined(XtSpecificationRelease) && (XtSpecificationRelease >= 5))
+/*
+ * According to IETF RFC 2279, byte values of 0xfe and 0xff are
+ * not legal utf-8, but all others bytes are legal.
+ */
+#define islatin(c) (isprint((c)) || ((((unsigned char)(c)) <= 0xfd)))
+
+#define isallowed(c) (isascii((c)) || islatin((c)))
#endif
--- Imakefile
+++ Imakefile
@@ -8,7 +8,8 @@
XCOMM
XCOMM for Dell SVR4
XCOMM
-EXTRA_LIBRARIES = -lc -lucb
+#EXTRA_LIBRARIES = -lc -lucb
+EXTRA_DEFINES = -Wall -Wstrict-prototypes -Wmissing-prototypes
SRCS = mgdiff.c rundiff.c misc.c files.c spawn.c manual.c modal.c legend.c
OBJS = mgdiff.o rundiff.o misc.o files.o spawn.o manual.o modal.o legend.o
--- legend.c
+++ legend.c
@@ -1,4 +1,4 @@
-#ifndef lint
+#if 0
static char rcsid[] = "legend.c,v 2.0 1994/05/19 02:01:08 dan Exp";
#endif
--- Mgdiff.ad
+++ Mgdiff.ad
@@ -112,7 +112,7 @@
!
! this should only be defined in the site-wide file
!
-?.AppDefaultsVersion: 1
+?.AppDefaultsVersion: 2
?.Geometry: 800x600
@@ -215,10 +215,14 @@
*file_menu*button_3.Accelerator: Ctrl<Key>s
*file_menu*button_3.AcceleratorText: Ctrl+S
-*file_menu*button_4.XmString: Exit
-*file_menu*button_4.Mnemonic: E
-*file_menu*button_4.Accelerator: Ctrl<Key>c
-*file_menu*button_4.AcceleratorText: Ctrl+C
+*file_menu*button_4.XmString: Save As Left...
+*file_menu*button_5.XmString: Save As Right...
+
+*file_menu*button_6.XmString: Exit
+*file_menu*button_6.Mnemonic: E
+*file_menu*button_6.Accelerator: Ctrl<Key>c
+*file_menu*button_6.AcceleratorText: Ctrl+C
+
!
!
*view_menu*button_0.XmString: Previous
--- spawn.c
+++ spawn.c
@@ -1,4 +1,4 @@
-#ifndef lint
+#if 0
static char rcsid[] = "spawn.c,v 2.0 1994/05/19 02:01:23 dan Exp";
#endif
@@ -35,6 +35,11 @@
#include <stdlib.h>
#include <errno.h>
+#include <X11/Intrinsic.h>
+
+#include "mgdiff.h"
+#include "externs.h"
+
#define BLOCKSIZE 10
/*
@@ -105,7 +110,7 @@
argv[argc++] = NULL;
if (execvp (prog, argv) == -1) {
- (void) sprintf (buffer, "%s: %s: %s", progname, "exec", prog);
+ (void) snprintf (buffer, sizeof (buffer), "%s: %s: %s", progname, "exec", prog);
perror (buffer);
exit (2);
}
@@ -131,4 +136,5 @@
break;
}
/* NOTREACHED */
+ return NULL;
}
--- files.c
+++ files.c
@@ -1,9 +1,10 @@
-#ifndef lint
+#if 0
static char rcsid[] = "files.c,v 2.0 1994/05/19 02:01:06 dan Exp";
#endif
/*
* Copyright (c) 1994 Daniel Williams
+ * Copyright (c) 2003 Erik de Castro Lopo
*
* The X Consortium, and any party obtaining a copy of these files from
* the X Consortium, directly or indirectly, is granted, free of charge,
@@ -83,16 +84,18 @@
*/
static int is_ascii_text (char *filename)
{
- int fd, bytes, i;
+ int fd, bytes, i, ch;
char buffer[1024];
fd = open (filename, O_RDONLY);
bytes = read (fd, (void *) buffer, 1024);
(void) close (fd);
- for (i = 0; i < bytes; i++)
- if (!isascii (buffer[i]))
+ for (i = 0; i < bytes; i++) {
+ ch = buffer [i];
+ if (!isallowed(ch))
return (0);
+ }
return (1);
}
@@ -143,7 +146,7 @@
XmString xms;
Arg args[2];
- (void) sprintf (buffer, "%s: %s", msg1, msg2);
+ (void) snprintf (buffer, sizeof (buffer), "%s: %s", msg1, msg2);
xms = XmStringCreateLtoR (buffer, XmSTRING_DEFAULT_CHARSET);
XtSetArg (args[0], XmNmessageString, xms);
XtSetArg (args[1], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL);
@@ -318,7 +321,7 @@
Arg args[2];
int i;
char *dir;
- XmString xms;
+ XmString xms = NULL ;
shell = XtVaCreatePopupShell ("openfiles", xmDialogShellWidgetClass, parent,
XmNallowShellResize, True,
@@ -424,7 +427,7 @@
Arg args[2];
int i;
char *dir;
- XmString xms;
+ XmString xms = NULL ;
i = 0;
XtSetArg (args[i], XmNdeleteResponse, XmDO_NOTHING); i++;
@@ -477,7 +480,7 @@
Arg args[2];
int i;
char *dir;
- XmString xms;
+ XmString xms = NULL ;
i = 0;
XtSetArg (args[i], XmNdeleteResponse, XmDO_NOTHING); i++;
@@ -533,7 +536,7 @@
if (access (filename, W_OK) == 0) { /* file exists and can be written */
char buffer[1024];
- (void) sprintf (buffer, "Overwrite \"%s\"?", filename);
+ (void) snprintf (buffer, sizeof (buffer), "Overwrite \"%s\"?", filename);
if (modal_question (w, "Mgdiff Save Question", buffer)) {
set_cursor (shell);
if ((status = really_save_file (filename, (Block *) closure)) != 0) {
@@ -569,7 +572,7 @@
Arg args[3];
int i;
char *dir;
- XmString xms;
+ XmString xms = NULL ;
i = 0;
XtSetArg (args[i], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); i++;
@@ -618,18 +621,32 @@
return (status);
}
else if ((b->arr[LEFT].type == DIFF) && (b->arr[RIGHT].type == DIFF)) {
- assert (b->selected != NEITHER);
+ switch (b->selected) {
+ case BOTH:
+ fprintf (file, "<<<<<<< diff from left file\n");
+ if ((status = write_chunk (file, &b->arr[LEFT])) != 0)
+ return (status);
+ fprintf (file, "========\n");
+ if ((status = write_chunk (file, &b->arr[RIGHT])) != 0)
+ return (status);
+ fprintf (file, ">>>>>>> diff from right file\n");
+ break;
+ case LEFT:
+ case RIGHT:
if ((status = write_chunk (file, &b->arr[b->selected])) != 0)
return (status);
+ break;
+ case NEITHER:
+ break;
+ default : assert (False);
+ }
}
else if ((b->arr[LEFT].type == INSERT) && (b->arr[RIGHT].type == BLANK)) {
- assert (b->selected != NEITHER);
if (b->selected == LEFT)
if ((status = write_chunk (file, &b->arr[LEFT])) != 0)
return (status);
}
else if ((b->arr[LEFT].type == BLANK) && (b->arr[RIGHT].type == INSERT)) {
- assert (b->selected != NEITHER);
if (b->selected == RIGHT)
if ((status = write_chunk (file, &b->arr[RIGHT])) != 0)
return (status);
@@ -669,3 +686,45 @@
return (0);
}
+
+void save_as_filename (Widget parent, Block *closure, char *filename)
+{
+ char *title = "Mgdiff Save Error";
+ int status;
+ Widget shell = get_top_shell (parent);
+
+ if (access (filename, W_OK) == 0) {
+ /* file exists and can be written */
+ char buffer[1024];
+
+ (void) snprintf (buffer, sizeof (buffer), "Overwrite \"%s\"?", filename);
+ if (modal_question (parent, "Mgdiff Save Question", buffer)) {
+ set_cursor (shell);
+ if ((status = really_save_file (filename, (Block *) closure)) != 0) {
+ reset_cursor (shell);
+ werror (parent, title, filename, strerror (status));
+ return;
+ }
+ reset_cursor (shell) ;
+ }
+ }
+ else {
+ /* file can't be written to */
+ if (errno == ENOENT) {
+ /* because it doesn't exist */
+ set_cursor (shell);
+ if ((status = really_save_file (filename, (Block *) closure)) != 0) {
+ reset_cursor (shell);
+ werror (parent, title, filename, strerror (status));
+ return;
+ }
+ reset_cursor (shell);
+ }
+ else {
+ /* for some other reason */
+ werror (parent, title, filename, strerror (errno));
+ return;
+ }
+ }
+
+} /* save_as_filename */
--- manual.c
+++ manual.c
@@ -1,4 +1,4 @@
-#ifndef lint
+#if 0
static char rcsid[] = "manual.c,v 2.0 1994/05/19 02:01:09 dan Exp";
#endif
@@ -134,14 +134,14 @@
if (value == NULL) { /* system calls in popen failed */
char buffer[1024];
- (void) sprintf (buffer, "System routine \"popen\" failed executing\nthis command (resource \"manCommand\"):\n\n\"%s\"", cmd);
+ (void) snprintf (buffer, sizeof (buffer), "System routine \"popen\" failed executing\nthis command (resource \"manCommand\"):\n\n\"%s\"", cmd);
xms = XmStringCreateLtoR (buffer, XmSTRING_DEFAULT_CHARSET);
iserror = 1;
}
else if (value[0] == '\0') { /* command produced no output */
char buffer[1024];
- (void) sprintf (buffer, "Shell command (resource \"manCommand\"):\n\n\"%s\"\n\nproduced no output", cmd);
+ (void) snprintf (buffer, sizeof (buffer), "Shell command (resource \"manCommand\"):\n\n\"%s\"\n\nproduced no output", cmd);
xms = XmStringCreateLtoR (buffer, XmSTRING_DEFAULT_CHARSET);
iserror = 1;
}
@@ -151,7 +151,7 @@
if ((tmp = strrchr (value, '\n')) != NULL)
*tmp = '\0';
- (void) sprintf (buffer, "Shell command (resource \"manCommand\"):\n\n \"%s\"\n\nproduced this output: \n\n \"%s\"", cmd, value);
+ (void) snprintf (buffer, sizeof (buffer), "Shell command (resource \"manCommand\"):\n\n \"%s\"\n\nproduced this output: \n\n \"%s\"", cmd, value);
xms = XmStringCreateLtoR (buffer, XmSTRING_DEFAULT_CHARSET);
iserror = 1;
}
--- debian/README.debian
+++ debian/README.debian
@@ -0,0 +1,39 @@
+mgdiff for DEBIAN
+----------------------
+
+I've added an awk script called "rmgdiff" that allows you to use
+mgdiff (or tkdiff etc.) to graphically and recursively diff two
+directories.
+
+Paul Serice <ugs@debian.org>, Tue, 25 Aug 1998 23:05:16 -0500
+
+ -----------------------------
+
+I've applied lots of patches from Erik de Castro Lopo <erikd AT
+mega-nerd DOT com>. Main new features for the user are:
+
+ - Save As Left... / Save As Right... in File menu
+ - saving without having selected all textblocks is possible
+ - click-middle-button selects both sides, the resulting file gets
+ markers like CVS uses
+ - changes documented in manpage
+
+See the changelog entry of 1.0-20 for a complete list of changes and
+the manpage for more explanations of the new features. Thanks Erik,
+great work!
+
+Edelhard Becker <edelhard@debian.org>, Sat, 07 Jun 2003 16:02:26 +0200
+
+ -----------------------------
+
+I've got another useful patch from Roger Gammans <roger@computer-
+surgery.co.uk> which add two features (see his "Patch Viewer" page
+http://www.sandman.uklinux.net/patchv/default.html for more info):
+
+ - X Paste of the most recently selected diff hunk.
+ - A wrapper to view patches, by appliy them to a temporary file first
+
+The latter is installed as /usr/share/doc/mgdiff/viewpatch, thanks
+Roger!
+
+Edelhard Becker <edelhard@debian.org>, Thu, 08 Apr 2004 00:42:30 +0200
--- debian/control
+++ debian/control
@@ -0,0 +1,15 @@
+Source: mgdiff
+Section: text
+Priority: optional
+Maintainer: Edelhard Becker <edelhard@debian.org>
+Build-Depends: xutils, lesstif2-dev, debhelper (>= 4)
+Standards-Version: 3.6.1
+
+Package: mgdiff
+Architecture: any
+Depends: ${shlibs:Depends}, debianutils (>=1.7), file, mawk
+Description: xdiff clone
+ mgdiff is modeled after xdiff and provides a nice graphical interface
+ for comparing the contents of two text files. rmgdiff recurses down
+ two directories collating difference information and invoking mgdiff
+ whenever two text files differ.
--- debian/prerm
+++ debian/prerm
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+#DEBHELPER#
+
+if [ -L /usr/doc/mgdiff ]; then
+ rm -f /usr/doc/mgdiff
+fi
--- debian/rules
+++ debian/rules
@@ -0,0 +1,66 @@
+#!/usr/bin/make -f
+# Made with the aid of debmake, by Christoph Lameter,
+# based on the sample debian/rules file for GNU hello by Ian Jackson.
+
+export DH_COMPAT=4
+package=mgdiff
+
+build:
+ dh_testdir
+ xmkmf
+ make depend XMULIBONLY=""
+ make XMULIBONLY=""
+ touch build
+
+clean:
+ dh_testdir
+ -rm -f build
+ -make clean
+ -rm -f `find . -name "*~"`
+ -rm -rf debian/mgdiff debian/files* core debian/substvars
+
+binary-indep: build
+ dh_testdir
+ dh_testroot
+# There are no architecture-independent files to be uploaded
+# generated by this package. If there were any they would be
+# made here.
+
+binary-arch: build
+ dh_testdir
+ dh_testroot
+ -rm -rf debian/mgdiff
+ install -d debian/mgdiff debian/mgdiff/usr/bin debian/mgdiff/usr/share/man/man1 debian/mgdiff/usr/share/doc/mgdiff
+ make install BINDIR=`pwd`/debian/mgdiff/usr/bin \
+ XAPPLOADDIR=`pwd`/debian/mgdiff/etc/X11/app-defaults \
+ XMULIBONLY=""
+ make install.man MANDIR=`pwd`/debian/mgdiff/usr/share/man/man1 XMULIBONLY=""
+ mkdir -p debian/mgdiff/usr/lib/rmgdiff
+ install -m 755 debian/rmgdiff debian/mgdiff/usr/lib/rmgdiff
+ install -m 644 debian/rmgdiff.awk debian/mgdiff/usr/lib/rmgdiff
+ ln -s ../lib/rmgdiff/rmgdiff debian/mgdiff/usr/bin
+ install -m 755 debian/cvsmgdiff debian/mgdiff/usr/bin
+ install -m 644 debian/cvsmgdiff.1 debian/mgdiff/usr/share/man/man1
+ install -m 644 debian/rmgdiff.1x debian/mgdiff/usr/share/man/man1
+ install -m 644 debian/mgdiff.README debian/mgdiff/usr/share/doc/mgdiff
+ install -m 755 debian/viewpatch debian/mgdiff/usr/share/doc/mgdiff
+ chmod u+w debian/mgdiff/usr/share/man/man1/mgdiff.1x
+ chmod u+w debian/mgdiff/etc/X11/app-defaults/Mgdiff
+ dh_testdir
+ dh_installdirs
+ dh_installdocs
+ dh_installman
+ dh_installchangelogs
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+
+.PHONY: binary binary-arch binary-indep clean
--- debian/rmgdiff
+++ debian/rmgdiff
@@ -0,0 +1,183 @@
+#!/bin/sh
+
+# Default value for the RMGDIFF_GUI environment variable.
+: ${RMGDIFF_GUI:=/usr/bin/mgdiff}
+
+#
+# You shouldn't need to edit beneath here.
+#
+
+SHOW_FILE_TYPES="TRUE"
+USE_CVS=""
+DEBUG=""
+USE_GUI="TRUE"
+RMGDIFF_VERSION=""
+
+
+
+Usage() {
+cat <<-EOF
+
+Usage: `basename "$0"` [-b] [-c] [-d] [-g <gui>] [-n] [-v] <dir1> <dir2>
+
+ -b: basic reporting (no file type info will be printed)
+ -c: cvs files will be included in diff
+ -d: print debugging information
+ -g: which gui to use
+ -n: no gui will pop up
+ -v: version
+
+EOF
+}
+
+verify_exec () {
+ type "$1" 1>/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "$progname: Error: Unable to find executable for \"$1\"." >&2
+ exit 1
+ fi
+}
+
+# Some machines don't have a "readlink" command.
+read_link_via_ls() {
+ if [ $# -ne 1 ] ; then
+ echo "$progname: Internal Error: Invalid args for" \
+ "readlink_via_ls: $@" >&2
+ exit 1
+ fi
+
+ \ls -l "$1" | sed -e 's|.*-> ||'
+}
+
+
+# Some machines don't have a "realpath" command. follow_link_via_ls
+# does not pretend to be "realpath" because it will leave all sorts of
+# cruft in the path string, but it should eventuall reach a regular
+# file.
+follow_link_via_ls() {
+
+ if [ $# -ne 1 ] ; then
+ echo "$progname: Internal Error: Invalid args for" \
+ "follow_link_via_ls: $@" >&2
+ exit 1
+ fi
+
+ local_iteration_count=0
+ local_iteration_max=1024
+
+ # Prime the pump.
+ local_tmp=
+ local_rv="$1"
+
+ while [ $local_iteration_count -lt $local_iteration_max ] ; do
+
+ if [ ! -h "$local_rv" ] ; then
+ break
+ fi
+
+ local_tmp=`read_link_via_ls "$local_rv"`
+
+ # The "read_link_via_ls" above could result in an absolute
+ # path or a relative one. The Solaris /bin/sh does not
+ # support "${PSTREE_AWK_SCRIPT#/}". So, use grep instead.
+ echo "$local_tmp" | grep '^/' >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ # The path given by readlink was relative. So, we have a
+ # little more work to do because we need to prepend the
+ # same path used to reach the original symlink.
+ local_tmp=`dirname "$local_rv"`/"$local_tmp"
+ fi
+
+ local_rv="$local_tmp"
+
+ local_iteration_count=`expr $local_iteration_count + 1`
+
+ done
+
+ if [ $local_iteration_count -ge $local_iteration_max ] ; then
+ echo "$progname: Error: Symbolic link nesting is too deep when" \
+ "following \"$1\"." >&2
+ exit 1
+ fi
+
+ echo "$local_rv"
+
+}
+
+
+#
+# Script starts here.
+#
+
+progname="rmgdiff"
+verify_exec "basename"
+progname=`basename "$0"`
+
+verify_exec "awk"
+verify_exec "diff"
+verify_exec "dirname"
+verify_exec "expr"
+verify_exec "file"
+verify_exec "grep"
+verify_exec "ls"
+verify_exec "$RMGDIFF_GUI"
+verify_exec "sed"
+
+while getopts "bcdg:nv" OPT ; do
+ case "$OPT" in
+ b) SHOW_FILE_TYPES=""
+ ;;
+ c) USE_CVS="TRUE"
+ ;;
+ d) DEBUG="TRUE"
+ ;;
+ g) RMGDIFF_GUI="$OPTARG"
+ ;;
+ n) USE_GUI=""
+ ;;
+ v) RMGDIFF_VERSION="TRUE"
+ ;;
+ \?) Usage
+ exit 1
+ ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+#
+# Find the rmgdiff awk script. It is located in the same directory as
+# this shell script after following all the symlinks.
+#
+lib_dir=`follow_link_via_ls "$0"`
+RMGDIFF_AWK=`dirname "$lib_dir"`/rmgdiff.awk
+
+
+# If the user just wants the version ...
+if [ -n "$RMGDIFF_VERSION" ] ; then
+ exec awk -v version="$RMGDIFF_VERSION" -f "$RMGDIFF_AWK"
+fi
+
+if [ $# -lt 2 ] || [ $# -gt 2 ] ; then
+ Usage
+ exit 1
+fi
+
+if [ ! -d "$1" ] ; then
+ echo "$progname: dir1=\"$1\" is not a directory." 1>&2
+ exit 1
+fi
+
+if [ ! -d "$2" ] ; then
+ echo "$progname: dir2=\"$2\" is not a directory." 1>&2
+ exit 1
+fi
+
+exec diff -rq "$1" "$2" | awk -v debug="$DEBUG" \
+ -v dir1="$1" \
+ -v dir2="$2" \
+ -v rmgdiff_gui="$RMGDIFF_GUI" \
+ -v show_file_types="$SHOW_FILE_TYPES" \
+ -v use_cvs="$USE_CVS" \
+ -v use_gui="$USE_GUI" \
+ -v version="$RMGDIFF_VERSION" \
+ -f "$RMGDIFF_AWK"
--- debian/changelog
+++ debian/changelog
@@ -0,0 +1,264 @@
+mgdiff (1.0-28) unstable; urgency=low
+
+ * bug fixes by Javier Fernández-Sanguino Peña <jfs@debian.org>
+ - Insecure /tmp usage in viewpatch example script (Closes: #335188)
+ - mgdiff: Allows user to set both input as '-' (Closes: #335191)
+ Thanks Javier!
+
+ -- Edelhard Becker <edelhard@debian.org> Tue, 25 Oct 2005 22:48:37 +0200
+
+mgdiff (1.0-27) unstable; urgency=low
+
+ * updated Paul Serices rmgdiff shell and awk scripts to 1.8.1, available
+ from his rmgdiff page (see copyright file); this should fix problems with
+ filenames and dirs with spaces and gawk compatibility, thanks Paul!
+
+ -- Edelhard Becker <edelhard@debian.org> Thu, 23 Jun 2005 22:14:26 +0200
+
+mgdiff (1.0-26) unstable; urgency=low
+
+ * fixed rmgdiff.1x typo, thanks A Costa (Closes: #310343)
+
+ -- Edelhard Becker <edelhard@debian.org> Fri, 27 May 2005 17:37:17 +0200
+
+mgdiff (1.0-25) unstable; urgency=low
+
+ * switched to lesstif2, get rid of lesstif1
+ * switched to debhelper, get rid of debmake
+ * made debhelper version lintian-clean
+
+ -- Edelhard Becker <edelhard@debian.org> Sat, 12 Mar 2005 22:33:35 +0100
+
+mgdiff (1.0-24) unstable; urgency=low
+
+ * bug fixes by Erik de Castro Lopo <erikd AT mega-nerd DOT com>:
+ - clean compiler warnigs (Closes: #271623)
+ - fix Ctrl-U/Ctrl-P handling (Closes: #271624)
+ - fix UTF8 handling (Closes: #135854)
+ Thanks Erik!
+
+ -- Edelhard Becker <edelhard@debian.org> Thu, 7 Oct 2004 00:50:16 +0200
+
+mgdiff (1.0-23) unstable; urgency=low
+
+ * Removes Xmu references from the build process (Closes: Bug#256419, must
+ been there for ages, thanks Daniel).
+ * corrected manpage sections to 1x
+
+ -- Edelhard Becker <edelhard@debian.org> Sun, 27 Jun 2004 14:50:55 +0200
+
+mgdiff (1.0-22) unstable; urgency=low
+
+ * included Roger Gammans <rgammans@computer-surgery.co.uk> "Patch Viewer"
+ plus necessary mgdiff patch
+ * Bumped to standards version 3.6.1
+
+ -- Edelhard Becker <edelhard@debian.org> Thu, 8 Apr 2004 00:33:53 +0200
+
+mgdiff (1.0-21) unstable; urgency=low
+
+ * scrambled Eriks e-mail in the manpage also
+ * typo in man-page fixed (thx Erik pointing this out)
+
+ -- Edelhard Becker <edelhard@debian.org> Wed, 9 Jul 2003 16:33:07 +0200
+
+mgdiff (1.0-20) unstable; urgency=low
+
+ * applied lots of patches from Erik de Castro Lopo <erikd AT mega-nerd DOT
+ com> (explanations from his e-mail to me):
+ - mgdiff-includes.diff: Fix a couple of missing includes.
+ - mgdiff-islatin.diff: Fix a warning message.
+ - mgdiff-sun-fix.diff: A fix for SUN Solaris.
+ - mgdiff-tempfile.diff: Replace use of tempnam() with something more
+ secure.
+ - mgdiff-warnings.diff: Remove compiler warnings when using CFLAGS equal
+ to -g -O2 -Wall -Wstrict-prototypes -Wmissing-prototypes [eb: added the
+ flags to the Imakefile].
+ - mgdiff-snprintf.diff: Replace all usage of sprintf() with snprintf().
+ - mgdiff-save-left-right.diff: Add file menu entries for "Save as Left..."
+ and "Save as Right...". Includes increment of APP_DEFAULTS_VERSION
+ number, mods to Mgdiff.ad and checks for correct app-default value.
+ - mgdiff-save-unselected.diff: Allow saving files with unselected blocks.
+ - mgdiff-select-both.diff: Add ability to select both sides by clicking
+ with the middle button. When both sides are selected the two blocks are
+ written to the output file using markings similar to the markings CVS
+ palces in a file when a merge goes wrong.
+ - mgdiff-man.diff: Update the man page to reflect the above changes. Also
+ added my own copyright to a couple of files where I made anything more
+ than minor changes. I'm quite happy to have my changes under the same
+ license as the original code.
+ * changed maintainer address to debian account
+ * Bumped to standards version 3.5.10
+ * updated README
+
+ -- Edelhard Becker <edelhard@debian.org> Sat, 7 Jun 2003 16:07:42 +0200
+
+mgdiff (1.0-19) unstable; urgency=low
+
+ * Added NAME section to cvsmgdiff man page (closes: #141670).
+ * Bumped to standards version 3.5.8.0.
+ * New maintainer. Closes: #169554.
+
+ -- Edelhard Becker <becker@edelhard.de> Wed, 26 Feb 2003 19:01:20 +0100
+
+mgdiff (1.0-18) unstable; urgency=low
+
+ * Change source maintainer to myself (closes: #71915).
+ * Make cvsmgdiff a bash script (bash should handle anything pdksh does).
+ * Write a manpage for cvsmgdiff.
+ * Add dh_strip to rules (fixes lintian warning).
+ * Add debhelper to Build-Depends.
+
+ -- Ian Zimmerman <itz@speakeasy.org> Fri, 15 Feb 2002 12:38:38 -0800
+
+mgdiff (1.0-17) unstable; urgency=low
+
+ * Fixed not being able to specify the cvsmgdiff gui from the command
+ line. There is now a -g flag.
+ * Also fixed a problem with where mgdiff was not comming up when
+ the -r option was used exactly once on the command line.
+
+ -- Paul Serice <paul@serice.net> Tue, 5 Feb 2002 13:09:08 -0600
+
+mgdiff (1.0-16) unstable; urgency=low
+
+ * Better dependencies in the Debian "control" file.
+ * Introduced the "cvsmgdiff" script for comparing a revision in your
+ CVS archive with what is currently checked out or for comparing
+ two revision both of which are in the archive. It works with
+ "mgdiff" (of course), xdiff, xxdiff, and tkdiff (not that tkdiff
+ needs this script).
+ * Portable way to move rmgdiff.awk out of /usr/bin and into
+ /usr/lib/rmgdiff where it should have been in the first place.
+
+ -- Paul Serice <paul@serice.net> Sat, 26 Jan 2002 23:06:47 -0600
+
+mgdiff (1.0-15) unstable; urgency=low
+
+ * Debian QA Upload.
+ * New version built by Paul Serice <paul@serice.net>
+ Fri, 26 Oct 2001 03:19:15 -0500; Thank you for your contribution:
+ - This is getting embarrassing. Previous version introduced a bug
+ that caused the "only in" sanity check to be triggered (yes,
+ again) when a file was only in one directory but had a minimum
+ depth of 2.
+
+ -- Peter Palfrader <weasel@debian.org> Sun, 28 Oct 2001 01:55:22 +0200
+
+mgdiff (1.0-14) unstable; urgency=low
+
+ * Debian QA Upload.
+ * New version built by Paul Serice <paul@serice.net>
+ Thu, 27 Sep 2001 20:33:15 -0500; Thanks Paul:
+ - Fatal bug in rmgdiff caused by working on two directories the last
+ one was a superstring of the first one is fixed.
+ * Removed emacs mode commands from debian/changelog.
+ * /etc/X11/app-defaults/Mgdiff tagged as conffile.
+
+ -- Peter Palfrader <weasel@debian.org> Sat, 29 Sep 2001 23:24:31 +0200
+
+mgdiff (1.0-13) unstable; urgency=low
+
+ * Debian QA Upload.
+ * Changed maintainer email address from debian-qa@lists.debian.org
+ to packages@qa.debian.org.
+ * New version built by Paul Serice <paul@serice.net>
+ Fri, 21 Sep 2001 01:29:06 -0500; Thanks Paul:
+ - Merged patch from Polish(ed) distribution, closes: #96085
+ (mgdiff has wrong heuristics for determining whether a file is
+ text or not).
+ - rmgdiff failed to escape meta-characters in directory names causing
+ directories like "c++_src" to trigger a sanity check.
+
+ -- Peter Palfrader <weasel@debian.org> Sat, 22 Sep 2001 15:42:00 +0200
+
+mgdiff (1.0-12) unstable; urgency=low
+
+ * Fixed RMGDIFF_GUI variable in /usr/bin/rmgdiff.
+ * Added license and author of rmgdiff to copyright file.
+ * Thanks Paul, closes: #87929.
+
+ -- Peter Palfrader <weasel@debian.org> Wed, 28 Feb 2001 03:40:31 +0000
+
+mgdiff (1.0-11) unstable; urgency=low
+
+ * Made Build-Depends: xutils, lesstif-dev, debmake (closes: #83848).
+ * Some app-defaults bugs have not been closed by last changelog:
+ (closes: #81421, #81383)
+ * Added support for DEB_BUILD_OPTIONS.
+ * Removed diff from Depends. diff is essential.
+ * Changed man path from usr/X11R6/man to /usr/share/man.
+ * Install binaries in usr/bin instead of usr/X11R6/bin.
+ * Moved doc from /usr/doc to /usr/share/doc and create symlink.
+ * Calling dpkg-gencontrol with -isp now, so Section and Priority fields
+ are in the pacakge.
+
+ -- Peter Palfrader <weasel@debian.org> Sat, 24 Feb 2001 17:39:49 +0000
+
+mgdiff (1.0-10) unstable; urgency=low
+
+ * Rebuilt to move app-defaults file to /etc/X11, Closes: #86278
+
+ -- Joey Hess <joeyh@debian.org> Fri, 16 Feb 2001 19:50:21 -0800
+
+mgdiff (1.0-9) unstable; urgency=low
+
+ * Paul orphaned the package a while back. Maintainer set to QA.
+
+ -- Joey Hess <joeyh@debian.org> Fri, 29 Dec 2000 18:47:27 -0800
+
+mgdiff (1.0-8) unstable; urgency=low
+
+ * Fixed error in man page for rmgdiff.
+
+ -- Paul Serice <ugs@debian.org> Sat, 13 Nov 1999 05:37:36 -0600
+
+mgdiff (1.0-7) unstable; urgency=low
+
+ * Added dependency on mawk.
+ * Fixed usage for rmgdiff: -m should be -g.
+
+ -- Paul Serice <ugs@debian.org> Tue, 26 Oct 1999 21:09:52 -0500
+
+mgdiff (1.0-6) unstable; urgency=low
+
+ * Linked against lesstif1. Closes bug #48167.
+
+ -- Paul Serice <ugs@debian.org> Sun, 24 Oct 1999 21:23:31 -0500
+
+mgdiff (1.0-5) unstable; urgency=low
+
+ * Added needed dependency on "file".
+
+ -- Paul Serice <ugs@debian.org> Sat, 8 May 1999 15:30:37 -0500
+
+mgdiff (1.0-4) unstable; urgency=low
+
+ * I wrote "rmgdiff" to allow the user to recursively diff two
+ directories using any graphical diff viewer -- including
+ mgdiff.
+ * Compiled using libc6 with new naming convention.
+ * mgdiff man page was not in the correct directory.
+ * Added "mgdiff.README".
+ * Now using original source in tarball.
+
+ -- Paul Serice <ugs@debian.org> Sun, 17 Jan 1999 23:05:44 -0600
+
+mgdiff (1.0-3) unstable; urgency=low
+
+ * Updated description to reflect Lesstif improvements.
+ * Changed architecture to 'any'.
+
+ -- Paul Serice <ugs@debian.org> Mon, 26 Oct 1998 01:16:45 -0600
+
+mgdiff (1.0-2) unstable; urgency=low
+
+ * Changed architecture to all.
+
+ -- Paul Serice <ugs@debian.org> Sat, 24 Oct 1998 23:08:56 -0500
+
+mgdiff (1.0-1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Paul Serice <ugs@debian.org> Tue, 25 Aug 1998 23:05:16 -0500
--- debian/cvsmgdiff.1
+++ debian/cvsmgdiff.1
@@ -0,0 +1,182 @@
+.\" Automatically generated by Pod::Man version 1.16
+.\" Fri Feb 15 12:01:43 2002
+.\"
+.\" Standard preamble:
+.\" ======================================================================
+.de Sh \" Subsection heading
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. | will give a
+.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used
+.\" to do unbreakable dashes and therefore won't be available. \*(C` and
+.\" \*(C' expand to `' in nroff, nothing in troff, for use with C<>
+.tr \(*W-|\(bv\*(Tr
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+'br\}
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr
+.\" for titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and
+.\" index entries marked with X<> in POD. Of course, you'll have to process
+.\" the output yourself in some meaningful fashion.
+.if \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. nr % 0
+. rr F
+.\}
+.\"
+.\" For nroff, turn off justification. Always turn off hyphenation; it
+.\" makes way too many mistakes in technical documents.
+.hy 0
+.if n .na
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ======================================================================
+.\"
+.IX Title "CVSMGDIFF 1"
+.TH CVSMGDIFF 1 "Utility Scripts" "2002-02-15" "Utility Scripts"
+.SH NAME
+cvsmgdiff \- uses mgdiff to display differences between any two cvs revisions.
+.UC
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+\&\fBcvsmgdiff\fR [\fB\-v\fR|\fB\-h\fR|\fB\-g\fR \fIgui\fR|\fB\-r\fR \fIrev1\fR [\fB\-r\fR \fIrev2\fR]] \fIfile\fR ...
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+This manual page documents briefly the cvsmgdiff program.
+This manual page was written for the Debian GNU/Linux distribution
+(but may be used by others), because the original
+program does not have a manual page.
+.PP
+This script lets you recursively diff the \s-1CVS\s0 directories you have
+checked out. To use, just pass in an optional revision levels and
+an optional file directory name. This script then will show you the
+differences you're interested in.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+.Ip "\fB\-v\fR" 4
+.IX Item "-v"
+Print version information successfully
+.Ip "\fB\-h\fR" 4
+.IX Item "-h"
+Print help information
+.Ip "\fB\-g\fR \fIgui\fR" 4
+.IX Item "-g gui"
+Use the program \fIgui\fR as the user interface (default: \fI/usr/bin/mgdiff\fR)
+.Ip "\fB\-r\fR \fIrevision\fR" 4
+.IX Item "-r revision"
+Specify the \s-1CVS\s0 revision to view. If just one \fB\-r\fR option is given, view
+differences between that revision and the current file in the \s-1CVS\s0 working
+directory. If two \fB\-r\fR options are given, compare those two revisions
+with each other.
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+cvsmgdiff appears to have been written by Paul Serice.
+This manual page was written by Ian Zimmerman <itz@speakeasy.org>
+for the Debian GNU/Linux project, but may
+be used by others. It was written with the assistance of
+\&\fIpod2man\fR\|(1).
--- debian/mgdiff.README
+++ debian/mgdiff.README
@@ -0,0 +1,44 @@
+Mon May 16 21:52:32 EDT 1994
+
+This is mgdiff, a graphical front end to the Unix diff command based
+upon X11R[456] and the Motif widget set. It allows the user to select
+two files for comparison, runs the diff command, parses the output and
+presents the results graphically. This presentation can also be used
+to generate a user-specified merge of the two files into a third file.
+
+This program's appearance is based upon a program called gdiff, which
+runs only on Silicon Graphics workstations and for which source code
+is not provided.
+
+The program has been developed and tested in the following
+environment:
+
+ - Dell SVR4 Issue 2.2
+ - cc and gcc 2.3.3
+ - X11R4 and X11R5
+ - Motif 1.1.4
+
+It has received some testing using SGI IRIX 5.2 with cc, X11R5 and
+Motif 1.2.3.
+
+It should build fairly painlessly with the Imakefile provided. You
+may need to point the Imakefile at your Motif libraries.
+
+You will need to install the application defaults file correctly for
+the program to run at all.
+
+An XPM icon file is provided if your window manager can use it.
+
+A preformatted manual page is also provided for those who don't have
+DWB or it's equivalent.
+
+Please send your comments, bug reports, bug fixes etc. to:
+
+ mgdiff@sass.com
+
+Enjoy,
+Dan
+--
+Daniel Williams, Consultant | Systems & Scientific Software
+Internet: dan@sass.com | 263 Forrest Avenue
+Voice: (215) 885-1573 | Elkins Park, PA 19027
--- debian/cvsmgdiff
+++ debian/cvsmgdiff
@@ -0,0 +1,245 @@
+#! /bin/bash
+
+#
+# This script lets you recursively diff the CVS directories you have
+# checked out. To use, just pass in an optional revision levels and
+# an optional file directory name. This script then will show you the
+# differences you're interested in.
+#
+# -- Paul Serice
+#
+
+CVSMGDIFF_VERSION=1.1
+
+: ${MGDIFF:=/usr/bin/mgdiff}
+: ${TMP:=/tmp}
+
+function usage {
+ if [ $# -ne 1 ] ; then
+ echo "progname: Error: Invalid args for usage: \"$@\"" >&2
+ exit 1
+ fi
+ cmd=
+ cmd="$cmd echo >&2 ;"
+ cmd="$cmd echo \"Usage: $progname [-h] [-v]"
+ cmd="$cmd [-g <gui>] [[-r <rev1>] [-r <rev2>]] file\" >&$1 ;"
+ cmd="$cmd echo >&2"
+ eval "$cmd"
+ if [ $1 -eq 1 ] ; then
+ exit 0
+ fi
+ exit 1
+}
+
+function verify_exec {
+ if [ $# -ne 1 ] ; then
+ echo "$progname: Error: Invalid args for verify_exec: \"$@\"" >&2
+ exit 1
+ fi
+ if ! type "$1" >/dev/null 2>&1 ; then
+ echo "$progname: Error: Unable to find executable for \"$1\"." >&2
+ exit 1
+ fi
+}
+
+tmp_base="cvsmgdiff-$$."
+function clean_up {
+ # These signal handlers are rough. It is, as far as I can tell,
+ # impossible to pass in the name of the currently active temporary
+ # files. A reasonable alternative is to scan $TMP for files that
+ # match the pattern we use being careful not to allow a malicious
+ # user to trick us into deleting some other file.
+ find "$TMP" -maxdepth 1 \
+ -type f \
+ -links 1 \
+ -uid `id -u` \
+ -name "$tmp_base"'*' \
+ -print0 \
+ | xargs -r0 rm -f
+ exit 0
+}
+
+#
+# getunique() -- Finds two unique temporary file names.
+#
+getunique()
+{
+ old_umask=`umask`
+ umask 077
+ if ! tmp_file_1=$(mktemp -q "$TMP/${tmp_base}XXXXXX") ; then
+ echo "Error: Unable to allocate a necessary temporary file." >&2
+ exit 1
+ fi
+
+ if ! tmp_file_2=$(mktemp -q "$TMP/${tmp_base}XXXXXX") ; then
+ echo "Error: Unable to allocate a necessary temporary file." >&2
+ exit 1
+ fi
+ umask $old_umask
+}
+
+#
+# Script Starts Here !!!
+#
+
+progname="cvsmgdiff.sh"
+verify_exec "basename"
+progname=`basename $0`
+
+# Signal Trap handler to clean up temporary files in "$TMP".
+if ! trap 'clean_up' HUP INT QUIT TERM ; then
+ echo "$progname: Unable to register signal handler." >&2
+ exit 1
+fi
+
+# Get cvs revision(s) to use.
+cnt=0
+while getopts "g:hr:v" OPT ; do
+ case "$OPT" in
+ g) MGDIFF="$OPTARG"
+ ;;
+ h) usage 1
+ ;;
+ r) rev[$cnt]="-r$OPTARG"
+ cnt=`expr $cnt + 1`
+ ;;
+ v) echo "$progname: ${CVSMGDIFF_VERSION}"
+ exit 0
+ ;;
+ \?) usage 2
+ ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+verify_exec "cut"
+verify_exec "cvs"
+verify_exec "echo"
+verify_exec "expr"
+verify_exec "find"
+verify_exec "grep"
+verify_exec "$MGDIFF"
+verify_exec "mktemp"
+verify_exec "sleep"
+verify_exec "xargs"
+
+mgdiff_basename=`basename "$MGDIFF"`
+
+# Portability issues.
+if [ "$mgdiff_basename" = "mgdiff" ] ; then
+ QUIET_OPT="-quit"
+ FNAME_OPT="-file"
+elif [ "$mgdiff_basename" = "xdiff" ] ; then
+ QUIET_OPT="-D"
+ FNAME_OPT="-N"
+elif [ "$mgdiff_basename" = "xxdiff" ] ; then
+ QUIET_OPT="-D"
+ FNAME_OPT="-N"
+ TITLE_1_OPT="--title1"
+ TITLE_2_OPT="--title2"
+fi
+
+if [ $cnt -gt 2 ] ; then
+ echo
+ echo "Error: Too many revisions."
+ echo
+ exit 1
+fi
+
+if [ ! -d `pwd`"/CVS" ] && [ ! -d `pwd`"/$1/CVS" ] ; then
+ echo
+ echo "Warning: \"$1\" does not appear to be a CVS directory." 1>&2
+ echo "Trying to diff \"$1\" with CVS repository anyway."
+ echo
+ sleep 5
+fi
+
+# Run CVS recursively on the entire directory.
+cvs diff "${rev[@]}" "$@" 2>/dev/null \
+| grep '^Index:' \
+| cut -d ' ' -f 2 \
+| while read fname ; do
+
+ echo -n "Processing $fname . . . "
+
+ # tkdiff CVS access built-in.
+ if [ "$mgdiff_basename" = "tkdiff" ] ; then
+
+ "$MGDIFF" ${rev[0]+"${rev[@]}"} "$fname"
+
+ # The others require a little bit of scripting.
+ elif [ $cnt -eq 2 ] ; then
+
+ getunique
+
+ \cvs update -p "${rev[0]}" "$fname" > "$tmp_file_1" 2> /dev/null
+ \cvs update -p "${rev[1]}" "$fname" > "$tmp_file_2" 2> /dev/null
+
+ "$MGDIFF" ${QUIET_OPT+"$QUIET_OPT"} \
+ ${TITLE_1_OPT+"$TITLE_1_OPT" "$fname (rev ${rev[0]#-r})"} \
+ ${TITLE_2_OPT+"$TITLE_2_OPT" "$fname (rev ${rev[1]#-r})"} \
+ "$tmp_file_1" "$tmp_file_2"
+
+ \rm -f "$tmp_file_1" > /dev/null 2>&1
+ \rm -f "$tmp_file_2" > /dev/null 2>&1
+
+ elif [ $cnt -le 1 ] ; then
+
+ if [ $cnt -eq 1 ] ; then
+ title_rev="${rev[0]#-r}"
+ else
+ title_rev=`cvs status "$fname" \
+ | grep 'Working revision:' \
+ | awk '{print $3;}'`
+ fi
+
+ # For some reason, xxdiff does not like to work with pipes
+ # despite its saying otherwise.
+ if [ "$TITLE_1_OPT" ] ; then
+
+ getunique
+
+ # The convention that "diff" uses is that the old file is on
+ # the left and the new file is on the right. We use this to
+ # display the files for all but "mgdiff" which has a
+ # "File->Save As..." menu option that works better the other
+ # way around.
+ file_first="$tmp_file_1"
+ file_second="$fname"
+ if [ "$mgdiff_basename" = "mgdiff" ] ; then
+ file_first="$fname"
+ file_second="$tmp_file_1"
+ fi
+
+ cvs update -p ${rev[0]+"${rev[0]}"} "$fname" \
+ > "$tmp_file_1" 2>/dev/null
+
+ "$MGDIFF" ${QUIET_OPT+"$QUIET_OPT"} \
+ ${TITLE_1_OPT+"$TITLE_1_OPT" "$fname (rev $title_rev)"}\
+ "$file_first" "$file_second"
+
+ \rm -f "$tmp_file_1" > /dev/null 2>&1
+ \rm -f "$tmp_file_2" > /dev/null 2>&1
+
+ else
+
+ # See comment above.
+ file_first="-"
+ file_second="$fname"
+ if [ "$mgdiff_basename" = "mgdiff" ] ; then
+ file_first="$fname"
+ file_second="-"
+ fi
+
+ cvs update -p ${rev[0]+"${rev[0]}"} "$fname" 2>/dev/null \
+ | "$MGDIFF" ${QUIET_OPT+"$QUIET_OPT"} \
+ ${FNAME_OPT+"$FNAME_OPT" "$fname (rev $title_rev)"} \
+ "$file_first" "$file_second"
+
+ fi
+
+ fi
+
+ echo "Done."
+
+ done
--- debian/viewpatch
+++ debian/viewpatch
@@ -0,0 +1,33 @@
+#!/bin/sh
+##
+#
+# (C) Roger Gammans 2001 (rgammans@computer-surgery.co.uk).
+#
+# Please distribute under the GPL.
+#
+# It's probably better to rely on the $PATH
+# to find the various external bits as they more likey
+# to be in it somewhere than one particluar location
+# over many unices.
+#
+
+FNAME=`tempfile` || { echo "$0: Cannot create temporary file" >&2; exit 1; }
+trap " [ -f \"$FNAME\" ] && /bin/rm -f -- \"$FNAME\"" 0 1 2 3 13 15
+
+ORIG=$1
+PATCH=$2
+
+shift 2
+
+if [ -z "$ORIG" ] || [ ! -e "$ORIG" ] ; then
+ echo "$0: original file '$ORIG' does not exist"
+fi
+if [ -z "$PATCH" ] || [ ! -e "$PATCH" ] ; then
+ echo "$0: original file '$ORIG' does not exist"
+fi
+
+
+cp $ORIG $FNAME;
+if patch $* $FNAME < $PATCH; then mgdiff $ORIG $FNAME; fi
+
+exit 0
--- debian/rmgdiff.1x
+++ debian/rmgdiff.1x
@@ -0,0 +1,98 @@
+.na
+.TH RMGDIFF 1x
+.SH NAME
+rmgdiff \- use almost any graphical file difference browser to recursively
+view the differences between two directories.
+.SH SYNOPSIS
+rmgdiff [-b] [-d] [-g gui] [-n] dir1 dir2
+.SH DESCRIPTION
+.LP
+.I rmgdiff
+is an awk script that works in conjunction with almost any graphical file
+difference browser. It is known to work with
+.IR mgdiff ,
+.IR tkdiff ,
+and
+.IR xdiff .
+.LP
+Unless I am mistaken, most of the GUI difference viewers (except for emacs)
+do not have built-in support for recursing down two directories, but
+.I diff
+does. Based on
+.IR diff 's
+output,
+.I rmgdiff
+decides when to invoke the graphical difference viewer.
+.LP
+In addition,
+.I rmgdiff
+also collates
+.IR diff 's
+output. As soon as a new difference is encountered in a text file,
+.I rmgdiff
+will print to standard output the name of the file that both directories have
+in common. It will then start the GUI and block until the user exits.
+As more text files with differences are found, the GUI will be started up
+again.
+.LP
+In the interim,
+.I rmgdiff
+will keep track of differences in binary (non-text) files. It organizes
+the binary files as executables, shared libraries, static libraries, object
+files, and other. Only after all the text files have been displayed will
+.I rmgdiff
+report the binary differences.
+.LP
+It also keeps track of files and directories that
+.I diff
+reports as being only in one directory or another.
+.I rmgdiff
+organizes these entries by directory. Thus, files in one directory
+will be reported in one block, and files that are in the other directory
+will be reported in a different block.
+.LP
+In addition to printing the name of the files that are different,
+.I rmgdiff
+defaults to printing the relevant portion of the output from the
+.I file
+command. This has the unfortunate side-effect of slowing things down;
+however, I find this information to be invaluable. If you're just looking
+for a fast way to collate
+.IR diff 's
+output, try piping it into
+.I sort
+instead.
+
+.SH COMMAND LINE OPTIONS
+.TP 8
+.B \-b
+Sets the basic reporting mode. In basic mode, rmgdiff reports only
+file names. It does not report the file types involved.
+.TP 8
+.B \-c
+By default, files relating to
+.I CVS
+are ignored by
+.IR rmgdiff .
+If you want to include CVS files, use this option.
+.TP 8
+.B \-d
+Sets
+.I rmgdiff
+to print way too much debugging information.
+.TP 8
+\fB\-g\fP \fIgui\fP
+Tells
+.I rmgdiff
+which gui you would like to use for viewing differences. By default,
+.I mgdiff
+is used. You can also set $RMGDIFF_GUI in your environment, but it can
+be overridden with this option.
+.TP 8
+.B \-n
+.I rmgdiff
+will not invoke the gui. This is useful, if you only want to view the
+collated output.
+
+.SH AUTHOR
+Paul Serice (paul@serice.net)
--- debian/mgdiff.substvars
+++ debian/mgdiff.substvars
@@ -0,0 +1 @@
+shlibs:Depends=lesstif2, libc6 (>= 2.3.5-1), libice6 | xlibs (>> 4.1.0), libsm6 | xlibs (>> 4.1.0), libx11-6 | xlibs (>> 4.1.0), libxext6 | xlibs (>> 4.1.0), libxt6 | xlibs (>> 4.1.0)
--- debian/copyright
+++ debian/copyright
@@ -0,0 +1,42 @@
+This package was debianized by Paul Serice <ugs@debian.org> on
+Tue, 25 Aug 1998 23:05:16 -0500.
+
+It was downloaded from ftp://ftp.x.org/contrib/applications/mgdiff.tar.gz .
+
+Please note that rmgdiff is not a part of the mgdiff distribution. Instead,
+it was written by your humble Debian maintainer. rmgdiff is GNU
+copyrighted.
+
+The copyright for mgdiff as found in mgdiff.c of the source distribution
+is as follows:
+
+/*
+ * Copyright (c) 1994 Daniel Williams
+ *
+ * The X Consortium, and any party obtaining a copy of these files from
+ * the X Consortium, directly or indirectly, is granted, free of charge,
+ * a full and unrestricted irrevocable, world-wide, paid up,
+ * royalty-free, nonexclusive right and license to deal in this software
+ * and documentation files (the "Software"), including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons
+ * who receive copies from any such party to do so. This license
+ * includes without limitation a license to do the foregoing actions
+ * under any patents of the party supplying this software to the X
+ * Consortium. The following conditions apply:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL DANIEL WILLIAMS OR SYSTEMS & SCIENTIFIC SOFTWARE BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+rmgdiff was written by Paul Serice <paul@serice.net>. It has its homepage
+at http://www.serice.net/rmgdiff/ and is in public domain.
--- debian/rmgdiff.awk
+++ debian/rmgdiff.awk
@@ -0,0 +1,776 @@
+#
+# rmgdiff.awk
+# -- awk script to that reads standard input for the output
+# of "diff -rq <dir1> <dir2>". It then takes diff's
+# output and calls mgdiff once for each pair of text
+# files that differ. It prints out a message to this
+# effect. It then prints out a list of binary files
+# that have differences followed by a list of files
+# that appear only in the first directory followed by a
+# list of files that appear only in the second
+# directory.
+#
+# It expects you to pass in <dir1> and <dir2> on the
+# command line using awk's "-v" option. You should
+# find the shell script I use to call this file near
+# where you found this file.
+#
+# -- Paul Serice
+#
+
+#
+# Changes:
+#
+# v1.8.1 Minor clean up.
+#
+# v1.8.0 Testing revealed problems handling white space.
+#
+# v1.7 Fixed a problem with the regular expression that
+# escapes meta-characters in the escape_dir() function.
+# Now, both gawk and mawk should be able to interpret this
+# script.
+#
+# v1.6 Changed the "rmgdiff" shell script wrapper so that this
+# awk script does not have to be in the same directory.
+# You can now place both "rmgdiff" and "rmgdiff.awk" in
+# any directory and place a symbolic link in a "bin"
+# directory that points to the "rmgdiff" shell script.
+# The shell script will then follow the symbolic links
+# in order to find the "rmgdiff.awk" script. One way to
+# set this up is as follows:
+#
+# /usr/local/lib/rmgdiff/rmgdiff
+# /usr/local/lib/rmgdiff/rmgdiff.awk
+# /usr/local/bin/rmgdiff -> ../lib/rmgdiff/rmgdiff
+#
+# v1.5 I've said it before, and here I go again. This time
+# it's fixed. v1.4 introduced a new bug related to the same
+# section of code that v1.3 and v1.4 was trying to fix.
+# This new bug manifested itself when a subdirectory was
+# only in one directory and had a minimum depth of at least
+# 2. Everything that was originally a bug and everything I
+# subsequently broke now appears to work.
+# v1.4 Was finally able to reproduce the bug that was causing
+# reported directories to appear to have been split
+# incorrectly. Problem solved.
+# v1.3 Forgot to escape the accidental meta-characters in the
+# directory names. Also, I am explicitly putting both the
+# "rmgdiff" shell script and this "rmgdiff.awk" awk script
+# in the public domain. (It has always been in the public
+# domain. This just makes it official. Use at your own
+# risk.)
+# v1.2 Changed the way the "rmgdiff" shell script initialized the
+# RMGDIFF_GUI variable.
+# v1.1 Fixed bug in "/^Binary file /" rule that used "$4" and "$6"
+# instead of "$3" and "$5".
+# v1.0 Initial release
+#
+
+#
+# trim_dir(dir) -- A user can enter a directory such as "dir", "dir/",
+# "dir//", etc. trim_dirr() will reduce all of these
+# to "dir" by removing all trailing slashes.
+#
+function trim_dir( dir , pos ) {
+ if( !dir )
+ return "";
+
+ pos = length(dir);
+ while( pos > 0 )
+ {
+ if( substr(dir, pos, 1) != "/" )
+ break;
+ pos--;
+ }
+
+ # If you made it back to the beginning, then "dir" was all slashes
+ # which is a synonym for the root dir.
+ if( pos <= 0 )
+ return "/";
+ else
+ return substr(dir, 1, pos);
+}
+
+
+#
+# escape_dir(dir) -- Escape the characters in the directory name that
+# are coincidentally meta characters.
+#
+function escape_dir(dir) {
+ gsub(/[[\]{}()^$. +|*?]/, "\\\\&", dir);
+ return dir;
+}
+
+
+#
+# relative_path(full_path, upper_dir)
+#
+# This function strips off the upper most directory. This
+# lets you report a difference just by reporting the relative
+# path. Thus, "dir1/abcd/efgh" and "dir2/abcd/efgh" can be
+# reported as being different by referring to "a difference in
+# the abcd/efgh files that reside in both directories."
+#
+function relative_path( full_path, upper_dir , pos ) {
+ if( index(full_path, upper_dir) != 1 )
+ {
+ print("***");
+ print("*** rmgdiff.awk: Internal error. ");
+ print("*** " upper_dir );
+ print("*** can't possibly be the base directory of ");
+ print("*** " full_path ".");
+ print("***");
+ exit_flag = 1;
+ exit(1);
+ }
+
+ pos = length(upper_dir) + 1;
+ full_path_len = length(full_path);
+
+ while( pos <= full_path_len )
+ {
+ if( substr(full_path, pos, 1) != "/")
+ break;
+ pos++;
+ }
+
+ # If "pos" makes it all the way to the end of "full_path", then the
+ # user passed in the name of a single directory instead of a path.
+ if( pos == length )
+ return "";
+ else
+ return substr(full_path, pos);
+}
+
+
+#
+# get_file_type() -- Returns the relevant part of the description returned
+# by "file". Unlike for Linux, the "file" command for
+# SGI will have in indeterminate number of spaces before
+# the relevant partion. Hence the iterative solution.
+# Perhaps it would be better to use 'FS= ' (?).
+#
+function get_file_type( file_name, \
+ cmd, pos, file_type, file_type_len, next_ch) {
+ cmd = file_cmd " \"" file_name "\"";
+ if( (cmd | getline file_type) == -1)
+ {
+ print("");
+ print("rmgdiff.awk: Unable to determine file type of " $2 ".");
+ print(" This usually occurs because you don't have any " \
+ "available");
+ print(" file descriptors or \"file\" is not in your path.");
+ print("");
+ exit_flag = 1;
+ exit(1);
+ }
+ close(cmd);
+
+ # Start right after the colon that always follows the file name.
+ pos = length(file_name) + 2;
+ file_type_len = length(file_type);
+
+ # Iterate until you find the first non-space and non-tab. I did it
+ # like this because different versions of Unix have different spacing.
+ while( pos <= file_type_len )
+ {
+ next_ch = substr(file_type, pos, 1);
+ if( (next_ch != " ") && (next_ch != "\t") )
+ break;
+ pos++;
+ }
+
+ if( pos > file_type_len )
+ {
+ print("***");
+ print("*** rmgdiff.awk: Internal error. Missed a file type for");
+ print("*** " file_name);
+ print("***");
+ exit_flag = 1;
+ exit(1);
+ }
+
+ return substr(file_type, pos);
+}
+
+
+#
+# add_only_in(dir, str3, str4) -- routine to convert $3 and $4 of the
+# output of diff when the file is only
+# in one directory into something we can
+# later print.
+#
+function add_only_in(dir, str3, str4 , middle, fullpath, file_type) {
+
+ middle = relative_path(str3, dir);
+
+ if( middle == "" )
+ fullpath = dir "/" str4;
+ else
+ fullpath = dir "/" middle "/" str4;
+
+ file_type = get_file_type(fullpath);
+
+ if( debug )
+ print("file_type = " file_type);
+
+ if( dir == dir1 )
+ {
+ if( debug )
+ print("Adding " fullpath " to only_in_dir1[" only_in_dir1_cnt "].");
+
+ if( show_file_types )
+ only_in_dir1[only_in_dir1_cnt++] = fullpath " (" file_type ")";
+ else
+ only_in_dir1[only_in_dir1_cnt++] = fullpath;
+ }
+ else if( dir == dir2 )
+ {
+ if( debug )
+ print("Adding " fullpath " to only_in_dir2[" only_in_dir2_cnt "].");
+
+ if( show_file_types )
+ only_in_dir2[only_in_dir2_cnt++] = fullpath " (" file_type ")";
+ else
+ only_in_dir2[only_in_dir2_cnt++] = fullpath;
+ }
+ else
+ {
+ print("***");
+ print("*** rmgdiff.awk: Internal error. Can't figure out " \
+ "\"only in\" directory.");
+ print("***");
+ exit_flag = 1;
+ exit(1);
+ }
+}
+
+
+
+#
+# add_binary(full_name_1, full_name_2)
+# -- Determines what type of binary a file is and adds it
+# to the appropriate list for reporting later. Make
+# sure "full_name_1" is the full_name associated with
+# "dir1" (which is a global variable).
+#
+
+function add_binary(full_name_1, full_name_2 , file_type_1, file_type_2) {
+ file_type_1 = get_file_type(full_name_1);
+ file_type_2 = get_file_type(full_name_2);
+
+ if( debug )
+ {
+ print("full_name_1 = " full_name_1);
+ print("full_name_2 = " full_name_2);
+ print("file_type_1 = " file_type_1);
+ print("file_type_2 = " file_type_2);
+ }
+
+ if( file_type_1 ~ /executable/ && file_type_2 ~ /executable/ )
+ {
+ if( debug )
+ print("Adding " relative_path(full_name_1, dir1) \
+ " to executable_files[" executable_files_cnt "].");
+
+ if( show_file_types )
+ executable_files[executable_files_cnt++] \
+ = relative_path(full_name_1, dir1) " (" file_type_1 ")";
+ else
+ executable_files[executable_files_cnt++] \
+ = relative_path(full_name_1, dir1);
+ }
+ else if( file_type_1 ~ /shared object/ && file_type_2 ~ /shared object/ )
+ {
+ if( debug )
+ print("Adding " relative_path(full_name_1, dir1) " to shared_libs[" \
+ shared_libs_cnt "].");
+
+ if( show_file_types )
+ shared_libs[shared_libs_cnt++] \
+ = relative_path(full_name_1, dir1) " (" file_type_1 ")";
+ else
+ shared_libs[shared_libs_cnt++] \
+ = relative_path(full_name_1, dir1);
+ }
+ else if( file_type_1 ~ /ar archive/ && file_type_2 ~ /ar archive/ )
+ {
+ if( debug )
+ print("Adding " relative_path(full_name_1, dir1) " to static_libs[" \
+ static_libs_cnt "].");
+
+ if( show_file_types )
+ static_libs[static_libs_cnt++] \
+ = relative_path(full_name_1, dir1) " (" file_type_1 ")";
+ else
+ static_libs[static_libs_cnt++] \
+ = relative_path(full_name_1, dir1);
+ }
+ else if( file_type_1 ~ /relocatable/ && file_type_2 ~ /relocatable/ )
+ {
+ if( debug )
+ print("Adding " relative_path(full_name_1, dir1) " to object_files[" \
+ object_files_cnt "].");
+
+ if( show_file_types )
+ object_files[object_files_cnt++] \
+ = relative_path(full_name_1, dir1) " (" file_type_1 ")";
+ else
+ object_files[object_files_cnt++] \
+ = relative_path(full_name_1, dir1);
+ }
+ # gzip files report a date which is causing them to appear
+ # to be mismatched. Avoid a mismatch with this rule.
+ else if ( file_type_1 ~ /gzip compressed data/ &&
+ file_type_2 ~ /gzip compressed data/ )
+ {
+ if( debug )
+ {
+ print("Matched a gzipped file. I'll be making up a type!!!");
+ print("Adding " relative_path(full_name_1, dir1) \
+ " to other_bin_files[" other_bin_files_cnt "].");
+ }
+
+ if( show_file_types )
+ other_bin_files[other_bin_files_cnt++] \
+ = relative_path(full_name_1, dir1) " (gzip compressed data)";
+ else
+ other_bin_files[other_bin_files_cnt++] \
+ = relative_path(full_name_1, dir1);
+ }
+ # Mismatched types.
+ else if ( file_type_1 !~ file_type_2 )
+ {
+ if( debug )
+ {
+ print("Adding " relative_path(full_name_1, dir1) \
+ " to mismatched_files[" mismatched_files_cnt "].");
+ print("File types differ!");
+ }
+
+ mismatched_files[mismatched_files_cnt++] \
+ = relative_path(full_name_1, dir1) \
+ " (Types differ. See next two lines.)\n" \
+ " " dir1 ": (" file_type_1 ")\n" \
+ " " dir2 ": (" file_type_2 ")";
+ }
+ else
+ {
+ if( debug )
+ print("Adding " relative_path(full_name_1, dir1) \
+ " to other_bin_files[" other_bin_files_cnt "].");
+
+ if( show_file_types )
+ other_bin_files[other_bin_files_cnt++] \
+ = relative_path(full_name_1, dir1) " (" file_type_1 ")";
+ else
+ other_bin_files[other_bin_files_cnt++] \
+ = relative_path(full_name_1, dir1);
+ }
+}
+
+
+#
+# add_text(full_name_1, full_name_2, file_type_1, file_type2)
+# -- We don't really need to "add" an entry to note that
+# we have found a text file. Instead, we go ahead and
+# print out the file's name and start up the GUI.
+#
+function add_text(full_name_1, full_name_2, file_type_1, file_type_2) {
+ if( debug )
+ {
+ print("full_name_1 = " full_name_1);
+ print("full_name_2 = " full_name_2);
+ print("file_type_1 = " file_type_1);
+ print("file_type_2 = " file_type_2);
+ }
+
+ if( first_diff )
+ {
+ printf("\n*** DIFFERENT TEXT FILES ***\n\n");
+ first_diff = 0;
+ }
+
+ if( file_type_1 == file_type_2 )
+ if( show_file_types )
+ print(relative_path(full_name_1, dir1) " (" file_type_1 ")");
+ else
+ print(relative_path(full_name_1, dir1));
+ else
+ {
+ print("=====");
+ print(relative_path(full_name_1, dir1) " (Types differ. " \
+ "See next two lines)");
+ print(" " dir1 ": (" file_type_1 ")");
+ print(" " dir2 ": (" file_type_2 ")");
+ print("=====");
+ }
+
+ if(use_gui)
+ system(rmgdiff_gui " \"" full_name_1 "\" \"" full_name_2 "\"");
+}
+
+
+#
+# add_text_or_binary(full_name_1, full_name_2)
+# -- Used to detect whether we have text files that differ
+# or something else. It sure would be nice if we could
+# pass these strings by reference.
+#
+function add_text_or_binary(full_name_1, full_name_2 , file_type_1, file_type_2)
+{
+ file_type_1 = get_file_type(full_name_1);
+ file_type_2 = get_file_type(full_name_2);
+
+ if( (file_type_1 ~ /text/ || file_type_1 ~ /^empty$/) &&
+ (file_type_2 ~ /text/ || file_type_2 ~ /^empty$/) )
+ {
+ add_text(full_name_1, full_name_2, file_type_1, file_type_2);
+ }
+ else
+ {
+ add_binary(full_name_1, full_name_2);
+ }
+}
+
+
+
+function check_exec(exec , cmd) {
+ cmd="type \"" exec "\" 1>/dev/null 2>&1";
+ if( system(cmd) != 0 )
+ {
+ printf("\nrmgdiff.awk: " exec " isn't executable.\n\n");
+ exit_flag = 1;
+ exit(1);
+ }
+}
+
+
+function check_dir(dir , cmd) {
+ cmd = "[ -d \"" dir "\" ]";
+ if( system(cmd) != 0 )
+ {
+ printf("\nrmgdiff.awk: \"" dir "\" isn't a directory.\n\n");
+ exit_flag = 1;
+ exit(1);
+ }
+}
+
+
+function check_external_executables() {
+ # You only need a gui if debug is off. Default to "mgdiff" if
+ # the user does not pass in a value.
+ if(use_gui && !rmgdiff_gui)
+ {
+ rmgdiff_gui = "mgdiff";
+ }
+ check_exec(rmgdiff_gui);
+
+ if(!file_cmd)
+ {
+ file_cmd = "file";
+ }
+ check_exec(file_cmd);
+
+ check_dir(dir1);
+ check_dir(dir2);
+}
+
+#
+# get_full_names(raw_diff_line, dir1, dir2, full_names)
+# -- This function takes the raw output of "diff -rq" for lines of
+# the form "... <file1> and <file2> differ" and returns <file1>
+# and <file2> in "full_names[1]" and "full_names[2]" respectively.
+# A special function is needed in order to account for those
+# cases where the file names have embedded spaces.
+#
+function get_full_names(raw_diff_line, dir1, dir2, full_names , regex) {
+ #
+ # full_names[2] -- The first call to gsub() strips off the trailing
+ # "differ". The second call to gsub() strips from the beginning of
+ # the string to the "and" that precedes <file2>. In case you missed
+ # it, we are calculating full_names[2] [sic] first.
+ #
+ full_names[2] = raw_diff_line;
+ gsub(/ differ$/, "", full_names[2]);
+ gsub("^.* and (" dir2 ")", dir2, full_names[2]);
+
+ #
+ # full_names[1] -- The first call to gsub() strips off the trailing
+ # "and <file2> differ". The second call to gsub() strips from the
+ # beginning of the string up to <file1>.
+ #
+ full_names[1] = raw_diff_line;
+ sub(" and " full_names[2] " differ$", "", full_names[1]);
+ sub("^.* " dir1, dir1, full_names[1]);
+
+ if( debug ) {
+ print("full_names[1] = " full_names[1]);
+ print("full_names[2] = " full_names[2]);
+ }
+}
+
+
+
+BEGIN {
+ if( debug )
+ print("Start BEGIN");
+
+ if( version )
+ {
+ printf("\nrmgdiff.awk: v1.8.1\n\n");
+ exit_flag = 1;
+ exit 1;
+ }
+
+ first_diff = 1; # Flag.
+
+ check_external_executables();
+
+ if( debug )
+ {
+ print("dir1 = " dir1);
+ print("dir2 = " dir2);
+ }
+
+ dir1 = trim_dir(dir1);
+ dir2 = trim_dir(dir2);
+
+ if( debug )
+ {
+ print("Trimmed dir1 to " dir1);
+ print("Trimmed dir2 to " dir2);
+ print("");
+ }
+
+ # When you want to match regular expressions, you need to escape any
+ # meta characters. For example, if your directory where "c++_src",
+ # and you try to do the match in the /^Only in/ that checks the
+ # following:
+ #
+ # if( "c++_src" ~ "^" "c++_src" )
+ #
+ # it will fail because the "++" in the last term are meta characters
+ # that aren't matched.
+ dir1_escaped = escape_dir(dir1);
+ dir2_escaped = escape_dir(dir2);
+
+ if( debug )
+ {
+ print("dir1 escaped to " dir1_escaped);
+ print("dir2 escaped to " dir2_escaped);
+ }
+
+ if( length(dir1_escaped) >= length(dir2_escaped) ) {
+ longer_dir = dir1;
+ longer_dir_escaped = dir1_escaped;
+ shorter_dir = dir2;
+ shorter_dir_escaped = dir2_escaped;
+ } else {
+ longer_dir = dir2;
+ longer_dir_escaped = dir2_escaped;
+ shorter_dir = dir1;
+ shorter_dir_escaped = dir1_escaped;
+ }
+
+ if( debug )
+ {
+ print("longer_dir = " longer_dir);
+ print("longer_dir_escaped = " longer_dir_escaped);
+ print("shorter_dir = " shorter_dir);
+ print("shorter_dir_escaped = " shorter_dir_escaped);
+ }
+
+}
+
+
+{
+ # Show the current line.
+ if( debug )
+ print("Current line: " $0);
+}
+
+
+
+# Find the files that differ. Filter out the CVS entries. Call mgdiff
+# if the file is a text file. If the file is a binary, save it for later.
+/^Files / {
+ if( debug )
+ print("Start Text and Binary files");
+
+ if( !use_cvs && $0 ~ /[ \/]CVS([ \/:]|$)/ )
+ {
+ if( debug )
+ print("Skipping CVS file.\n");
+ next;
+ }
+
+ full_names[1] = "";
+ full_names[2] = "";
+ get_full_names($0, dir1, dir2, full_names);
+
+ add_text_or_binary(full_names[1], full_names[2]);
+}
+
+
+# This is here for compatibility with the older version of GNU diff
+# that reported binary and text file differences separately.
+/^Binary files / {
+ if( debug )
+ print("Start Binary files only");
+
+ if( !use_cvs && $0 ~ /[ \/]CVS([ \/:]|$)/ )
+ {
+ if( debug )
+ print("Skipping CVS file.\n");
+ next;
+ }
+
+ full_names[1] = "";
+ full_names[2] = "";
+ get_full_names($0, dir1, dir2, full_names);
+
+ add_binary(full_names[1], full_names[2]);
+}
+
+# Find the files that are only in one of the directories. Filter out
+# the CVS entries. Sort into two arrays for later printing.
+/^Only in / {
+ if( debug )
+ print("Start Only in");
+
+ if( !use_cvs && $0 ~ /[ \/]CVS([ \/:]|$)/ )
+ {
+ if( debug )
+ print("Skipping CVS file.\n");
+ next;
+ }
+
+ # Find the directory.
+ only_in_dir = substr($0, length("Only in ") + 1);
+ gsub(/: .*$/, "", only_in_dir);
+
+ # Find the file that is only in "only_in_dir".
+ only_file = $0;
+ gsub(/^.*: /, "", only_file);
+
+ if( debug )
+ {
+ print("only_in_dir = " only_in_dir);
+ print("only_file = " only_file);
+ }
+
+ #
+ # A space means to concatenate the strings. So,
+ #
+ # only_in_dir ~ "^" longer_dir_escaped
+ #
+ #
+ # means you have a match if only_in_dir begins with longer_dir_escaped.
+ #
+ # You have to NOT anchor the end of the string to match. The reason
+ # is that you could easily get the situation where a file or
+ # directory is only in one of the directories you are recursively
+ # diffing, and it has a depth of 2 or more. (Note, "depth" here is
+ # the same concept as the "find" command's "-maxdepth" parameter.)
+ # This means you don't know what is going to be at the end of only_in_dir.
+ #
+ # You have to test the longer directory first because you might be
+ # diffing two directories named something like "my_dir" and
+ # "my_dir-v1.0". If you tested the shorter directory first, you
+ # would always get a match because when only_in_dir is the longer directory,
+ # it too matches the shorter directory.
+ #
+
+ if( only_in_dir ~ "^" longer_dir_escaped ) {
+ add_only_in(longer_dir, only_in_dir, only_file);
+ }
+ else if( only_in_dir ~ "^" shorter_dir_escaped ) {
+ add_only_in(shorter_dir, only_in_dir, only_file);
+ } else {
+ print("***");
+ print("*** rmgdiff.awk: Internal error. Missed an \"only in\".");
+ print("*** only_in_dir = " only_in_dir);
+ print("***");
+ exit_flag = 1;
+ exit(1);
+ }
+
+}
+
+
+# Just print a line to separate output for each pass.
+{
+ if( debug )
+ print("");
+}
+
+
+# Print out the entries you earlier saved to an array.
+END {
+ if( !exit_flag )
+ {
+
+ # I decided to not create a separate function for printing
+ # reports because you can't pass these potentially large
+ # arrays by reference.
+
+ if( executable_files_cnt )
+ {
+ printf("\n*** DIFFERENT EXECUTABLES ***\n\n");
+ for( i = 0 ; i < executable_files_cnt ; i++ )
+ print(executable_files[i]);
+ }
+
+ if( shared_libs_cnt )
+ {
+ printf("\n*** DIFFERENT SHARED LIBRARIES ***\n\n");
+ for( i = 0 ; i < shared_libs_cnt ; i++ )
+ print(shared_libs[i]);
+ }
+
+ if( static_libs_cnt )
+ {
+ printf("\n*** DIFFERENT STATIC LIBRARIES ***\n\n");
+ for( i = 0 ; i < static_libs_cnt ; i++ )
+ print(static_libs[i]);
+ }
+
+ if( object_files_cnt )
+ {
+ printf("\n*** DIFFERENT OBJECT FILES ***\n\n");
+ for( i = 0 ; i < object_files_cnt ; i++ )
+ print(object_files[i]);
+ }
+
+ if( other_bin_files_cnt )
+ {
+ printf("\n*** OTHER DIFFERENT BINARY FILES ***\n\n");
+ for( i = 0 ; i < other_bin_files_cnt ; i++ )
+ print(other_bin_files[i]);
+ }
+
+ if( only_in_dir1_cnt )
+ {
+ printf("\n*** FILES ONLY IN %s ***\n\n", dir1);
+ for( i = 0 ; i < only_in_dir1_cnt ; i++ )
+ print(only_in_dir1[i]);
+ }
+
+ if( only_in_dir2_cnt )
+ {
+ printf("\n*** FILES ONLY IN %s ***\n\n", dir2);
+ for( i = 0 ; i < only_in_dir2_cnt ; i++ )
+ print(only_in_dir2[i]);
+ }
+
+ if( mismatched_files_cnt )
+ {
+ printf("\n*** WARNING: MISMATCHED FILES ***\n\n");
+ for( i = 0 ; i < mismatched_files_cnt ; i++ )
+ print(mismatched_files[i]);
+ }
+
+ print("");
+ }
+}
--- modal.c
+++ modal.c
@@ -1,4 +1,4 @@
-#ifndef lint
+#if 0
static char rcsid[] = "modal.c,v 2.0 1994/05/19 02:01:20 dan Exp";
#endif
--- rundiff.c
+++ rundiff.c
@@ -1,4 +1,4 @@
-#ifndef lint
+#if 0
static char rcsid[] = "rundiff.c,v 2.0 1994/05/19 02:01:22 dan Exp";
#endif
@@ -209,7 +209,7 @@
FILE *diff, *file1, *file2;
char buffer[BUFSIZ+1];
int sline, fline1, fline2;
- Block *b;
+ Block *b = NULL;
int i, lines, counter;
int stat_loc;
DiffInfo *di;
@@ -245,7 +245,7 @@
char cmdline[4096];
di->etext = (char **) calloc (MAX_ERROR_LINES + 1, sizeof (char *));
- (void) sprintf (cmdline, " \"%s %s %s %s\"", prog, args, path1, path2);
+ (void) snprintf (cmdline, sizeof (cmdline), " \"%s %s %s %s\"", prog, args, path1, path2);
di->etext[di->errors++] = strdup ("diff command line:");
di->etext[di->errors++] = strdup ("");
di->etext[di->errors++] = strdup (cmdline);
@@ -522,21 +522,23 @@
*/
static char *duplicate (char *s, int *flag)
{
- int len, i, tabs, ctrls;
+ int len, i, tabs, ctrls, latin, ch;
/*
* compute length of new string, taking tabs and control
* characters into account
*/
for (i = 0, len = 0, ctrls = tabs = 0; s[i] != '\0'; i++) {
- if (isascii (s[i])) {
+ ch = s [i];
+ latin = islatin(ch);
+ if ((isascii(ch) || latin)) {
if (s[i] == '\t') {
tabs++;
len += 8;
len /= 8;
len *= 8;
}
- else if (iscntrl (s[i])) {
+ else if (!latin && iscntrl (s[i])) {
ctrls++;
len += 2;
}
@@ -551,16 +553,18 @@
if (tabs || ctrls) {
char *ret = (char *) calloc (1, len + 1);
- int j;
+ int j, ch;
for (i = 0, j = 0; s[i] != '\0'; i++) {
- if (isascii (s[i])) {
+ ch = s[i];
+ latin = islatin(ch);
+ if ((isascii(ch) || latin)) {
if (s[i] == '\t') {
ret[j++] = ' ';
while ((j % 8) != 0)
ret[j++] = ' ';
}
- else if (iscntrl (s[i])) {
+ else if (!latin && iscntrl (s[i])) {
ret[j++] = '^';
ret[j++] = (s[i] + '@') & 0x7f;
}
--- misc.c
+++ misc.c
@@ -1,9 +1,10 @@
-#ifndef lint
+#if 0
static char rcsid[] = "misc.c,v 2.0 1994/05/19 02:01:19 dan Exp";
#endif
/*
* Copyright (c) 1994 Daniel Williams
+ * Copyright (c) 2003 Erik de Castro Lopo
*
* The X Consortium, and any party obtaining a copy of these files from
* the X Consortium, directly or indirectly, is granted, free of charge,
@@ -33,6 +34,8 @@
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
#include <Xm/Xm.h>
#include <X11/cursorfont.h>
@@ -40,6 +43,7 @@
#include <Xm/SashP.h>
#include "mgdiff.h"
+#include "externs.h"
int max (int i, int j)
{
@@ -52,14 +56,38 @@
}
/*
- * copy a stream up to the EOF to a file
+ * Create a temporary file and write all text from the input stream (up to
+ * the EOF) to the file.
+ * The name of the temp file is returned to the user in *name.
*/
-int copy_to_file (FILE *fin, char *name)
+int copy_to_tempfile (FILE *fin, char *name, size_t name_len)
{
- FILE *fout;
+ FILE *fout ;
+ int fd ;
+
+ /*
+ ** Seed the random() generator. This does not need to be super
+ ** randomised as the while loop below will be run until a file
+ ** is opened.
+ */
+ srandom (getpid () + getppid () + time (NULL)) ;
+
+ while (1) {
+ snprintf (name, name_len, "/tmp/mgdiff-%#lx", random()) ;
+ if ((fd = open (name, O_CREAT | O_EXCL | O_RDWR, 0600)) < 0) {
+ if (errno == EEXIST)
+ continue ;
+ return 1 ;
+ }
+
+ if ((fout = fdopen (fd, "r+")) == NULL) {
+ close (fd) ;
+ return 1 ;
+ }
+
+ break ;
+ }
- if ((fout = fopen (name, "a")) == NULL)
- return (0);
while (!feof (fin)) {
char buffer[BUFSIZ];
int nitems;
@@ -68,10 +96,12 @@
if (fwrite (buffer, 1, nitems, fout) != nitems)
break;
}
+
if (ferror (fin) || ferror (fout)) {
(void) fclose (fout);
return (1);
}
+
return ((fclose (fout) == 0));
}
--- patchlevel.h
+++ patchlevel.h
@@ -28,11 +28,11 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef lint
+#if 0
static char rcsid_patchlevel_h[] = "patchlevel.h,v 2.0 1994/05/19 02:01:21 dan Exp";
#endif
#define VERSION "1.0"
-#define PATCHLEVEL "0"
+#define PATCHLEVEL "1"
#endif
--- externs.h
+++ externs.h
@@ -28,7 +28,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef lint
+#if 0
static char rcsid_externs_h[] = "externs.h,v 2.0 1994/05/19 02:01:05 dan Exp";
#endif
@@ -43,7 +43,7 @@
extern DiffInfo *build_diff_info (char *prog, char *args, char *path1, char *path2);
extern int max (int i, int j);
extern int min (int i, int j);
-extern int copy_to_file (FILE *fin, char *name);
+extern int copy_to_tempfile (FILE *fin, char *name, size_t name_len);
extern void set_cursor (Widget w);
extern void reset_cursor (Widget w);
extern Widget get_top_shell (Widget w);
@@ -61,5 +61,6 @@
extern void turn_off_sash_traversal (Widget pane);
extern void show_legend (Widget parent);
extern void show_context (Widget parent);
+extern void save_as_filename (Widget parent, Block *b, char *name);
#endif
--- mgdiff.man
+++ mgdiff.man
@@ -1,6 +1,7 @@
.\" mgdiff.man,v 2.0 1994/05/19 02:01:16 dan Exp
.\"
.\" Copyright (c) 1994 Daniel Williams
+.\" Copyright (c) 2003 Erik de Castro Lopo
.\"
.\" The X Consortium, and any party obtaining a copy of these files from
.\" the X Consortium, directly or indirectly, is granted, free of charge,
@@ -26,7 +27,7 @@
.\" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
.\"
.na
-.TH MGDIFF 1
+.TH MGDIFF 1x
.SH NAME
mgdiff \- Motif-based graphical file difference browser
.SH SYNOPSIS
@@ -82,6 +83,20 @@
.LP
At the top of the display is a Motif menu bar; those functions are
discussed in the MENUS section of this manual page.
+.LP
+Earlier versions of this program (pre 2003) only allowed the selection
+of the left hand side difference or the right hand side difference. It
+also would not allow a file to be saved with unselected blocks. The
+current version allows the user to select both sides of a difference
+by selecting blocks using the middle mouse button. When both sides of a
+difference are selected both blocks will be saved to the merged file and
+marked in a similar manner to the way
+.I CVS
+marks merges that require manual resolution of conflicting changes. In
+addition, the current version also allows saving of a merged file with
+unselected blocks. In this case, the merged file will contain
+neither the left hand side nor the right hand side of the unselected
+blocks.
.SH COMMAND LINE OPTIONS
.TP 8
@@ -170,8 +185,27 @@
application modal dialog. The program will allow the user to
overwrite an existing file but pops up a QuestionDialog to allow the
user to cancel the operation if desired. If there are any unselected
-areas of difference between the two files the user is notified via an
-ErrorDialog and the save operation is canceled.
+areas of difference between the two files the user is asked whether
+they want to continue or cancel the operation. If the user continues,
+the output file will contain none of the unselected blocks.
+.IP "\fBSave As Left...\fP" \n(XYP
+.LP
+Saves the merged file to the location given by the left hand side
+file location. The user will be asked if they are sure they wish the
+existing file to be overwritten. As with the "Save As", if there are
+any unselected areas of difference between the two files the user
+asked whether they want to continue or cancel the operation. If the
+user continues, the output file will contain none of the data in the
+unselected blocks.
+.IP "\fBSave As Right...\fP" \n(XYP
+.LP
+Saves the merged file to the location given by the right hand side
+file location. The user will be asked if they are sure they wish the
+existing file to be overwritten. As with the "Save As", if there are
+any unselected areas of difference between the two files the user
+asked whether they want to continue or cancel the operation. If the
+user continues, the output file will contain none of the data in the
+unselected blocks.
.IP "\fBExit\fP" \n(XYP
.B Ctrl+C
.LP
@@ -332,6 +366,9 @@
XmPushButtonGadget button_3
XmSeparatorGadget separator_0
XmPushButtonGadget button_4
+ XmPushButtonGadget button_5
+ XmSeparatorGadget separator_1
+ XmPushButtonGadget button_6
XmRowColumn options_menu
XmToggleButtonGadget button_0
XmToggleButtonGadget button_1
@@ -543,12 +580,17 @@
any quote processing.
.SH COPYRIGHT
Copyright (c) 1994, Daniel Williams
+.br
+Copyright (c) 2003, Erik de Castro Lopo
.br
See
.B X (1)
for a full statement of rights and permissions.
-.SH AUTHOR
+.SH AUTHORS
Daniel Williams (dan@sass.com)
+.br
+Erik de Castro Lopo (erikd AT mega-nerd DOT com) added "\fBSave as Left/Right\fP"
+and saving both and neither sides.
.SH ACKNOWLEDGEMENTS
To Andrew C. Myers for writing
.I gdiff.