Fossil SCM

Add the "diff optimizer" which tries to shift inserts and deletes to align with natural boundaries in the text. The resulting diff is no more or less correct than the original; it just seems more natural to human readers.

drh 2012-02-05 20:22 trunk
Commit 98cf5c33bc1529e44ecde9fb5dbc680a7121ab09
2 files changed +140 -22 +3
+140 -22
--- src/diff.c
+++ src/diff.c
@@ -33,10 +33,12 @@
3333
#define DIFF_SIDEBYSIDE 0x02000000 /* Generate a side-by-side diff */
3434
#define DIFF_NEWFILE 0x04000000 /* Missing files are as empty files */
3535
#define DIFF_INLINE 0x08000000 /* Inline (not side-by-side) diff */
3636
#define DIFF_HTML 0x10000000 /* Render for HTML */
3737
#define DIFF_LINENO 0x20000000 /* Show line numbers in context diff */
38
+#define DIFF_NOOPT 0x40000000 /* Suppress optimizations for debug */
39
+#define DIFF_INVERT 0x80000000 /* Invert the diff for debug */
3840
3941
#endif /* INTERFACE */
4042
4143
/*
4244
** Maximum length of a line in a text file. (8192)
@@ -61,10 +63,15 @@
6163
** above are one per line of input text. But each entry is also
6264
** a bucket in a hash table, as follows: */
6365
unsigned int iHash; /* 1+(first entry in the hash chain) */
6466
};
6567
68
+/*
69
+** Length of a dline
70
+*/
71
+#define LENGTH(X) ((X)->h & LENGTH_MASK)
72
+
6673
/*
6774
** A context for running a raw diff.
6875
**
6976
** The aEdit[] array describes the raw diff. Each triple of integers in
7077
** aEdit[] means:
@@ -876,10 +883,112 @@
876883
p->aEdit[p->nEdit++] = 0;
877884
p->aEdit[p->nEdit++] = 0;
878885
p->aEdit[p->nEdit++] = 0;
879886
}
880887
}
888
+
889
+/*
890
+** Attempt to shift insertion or deletion blocks so that they begin and
891
+** end on lines that are pure whitespace. In other words, try to transform
892
+** this:
893
+**
894
+** int func1(int x){
895
+** return x*10;
896
+** +}
897
+** +
898
+** +int func2(int x){
899
+** + return x*20;
900
+** }
901
+**
902
+** int func3(int x){
903
+** return x/5;
904
+** }
905
+**
906
+** Into one of these:
907
+**
908
+** int func1(int x){ int func1(int x){
909
+** return x*10; return x*10;
910
+** } }
911
+** +
912
+** +int func2(int x){ +int func2(int x){
913
+** + return x*20; + return x*20;
914
+** +} +}
915
+** +
916
+** int func3(int x){ int func3(int x){
917
+** return x/5; return x/5;
918
+** } }
919
+*/
920
+static void diff_optimize(DContext *p){
921
+ int r; /* Index of current triple */
922
+ int lnFrom; /* Line number in p->aFrom */
923
+ int lnTo; /* Line number in p->aTo */
924
+ int cpy, del, ins;
925
+
926
+ lnFrom = lnTo = 0;
927
+ for(r=0; r<p->nEdit; r += 3){
928
+ cpy = p->aEdit[r];
929
+ del = p->aEdit[r+1];
930
+ ins = p->aEdit[r+2];
931
+ lnFrom += cpy;
932
+ lnTo += cpy;
933
+
934
+ /* Shift insertions toward the beginning of the file */
935
+ while( cpy>0 && del==0 && ins>0 ){
936
+ DLine *pTop = &p->aFrom[lnFrom-1]; /* Line before start of insert */
937
+ DLine *pBtm = &p->aTo[lnTo+ins-1]; /* Last line inserted */
938
+ if( same_dline(pTop, pBtm)==0 ) break;
939
+ if( LENGTH(pTop+1)+LENGTH(pBtm)<=LENGTH(pTop)+LENGTH(pBtm-1) ) break;
940
+ lnFrom--;
941
+ lnTo--;
942
+ p->aEdit[r]--;
943
+ p->aEdit[r+3]++;
944
+ cpy--;
945
+ }
946
+
947
+ /* Shift insertions toward the end of the file */
948
+ while( p->aEdit[r+3]>0 && del==0 && ins>0 ){
949
+ DLine *pTop = &p->aTo[lnTo]; /* First line inserted */
950
+ DLine *pBtm = &p->aTo[lnTo+ins]; /* First line past end of insert */
951
+ if( same_dline(pTop, pBtm)==0 ) break;
952
+ if( LENGTH(pTop)+LENGTH(pBtm-1)<=LENGTH(pTop+1)+LENGTH(pBtm) ) break;
953
+ lnFrom++;
954
+ lnTo++;
955
+ p->aEdit[r]++;
956
+ p->aEdit[r+3]--;
957
+ cpy++;
958
+ }
959
+
960
+ /* Shift deletions toward the beginning of the file */
961
+ while( cpy>0 && del>0 && ins==0 ){
962
+ DLine *pTop = &p->aFrom[lnFrom-1]; /* Line before start of delete */
963
+ DLine *pBtm = &p->aFrom[lnFrom+del-1]; /* Last line deleted */
964
+ if( same_dline(pTop, pBtm)==0 ) break;
965
+ if( LENGTH(pTop+1)+LENGTH(pBtm)<=LENGTH(pTop)+LENGTH(pBtm-1) ) break;
966
+ lnFrom--;
967
+ lnTo--;
968
+ p->aEdit[r]--;
969
+ p->aEdit[r+3]++;
970
+ cpy--;
971
+ }
972
+
973
+ /* Shift deletions toward the end of the file */
974
+ while( p->aEdit[r+3]>0 && del>0 && ins==0 ){
975
+ DLine *pTop = &p->aFrom[lnFrom]; /* First line deleted */
976
+ DLine *pBtm = &p->aFrom[lnFrom+del]; /* First line past end of delete */
977
+ if( same_dline(pTop, pBtm)==0 ) break;
978
+ if( LENGTH(pTop)+LENGTH(pBtm-1)<=LENGTH(pTop)+LENGTH(pBtm) ) break;
979
+ lnFrom++;
980
+ lnTo++;
981
+ p->aEdit[r]++;
982
+ p->aEdit[r+3]--;
983
+ cpy++;
984
+ }
985
+
986
+ lnFrom += del;
987
+ lnTo += ins;
988
+ }
989
+}
881990
882991
/*
883992
** Extract the number of lines of context from diffFlags. Supply an
884993
** appropriate default if no context width is specified.
885994
*/
@@ -921,10 +1030,15 @@
9211030
){
9221031
int ignoreEolWs; /* Ignore whitespace at the end of lines */
9231032
int nContext; /* Amount of context to display */
9241033
DContext c;
9251034
1035
+ if( diffFlags & DIFF_INVERT ){
1036
+ Blob *pTemp = pA_Blob;
1037
+ pA_Blob = pB_Blob;
1038
+ pB_Blob = pTemp;
1039
+ }
9261040
nContext = diff_context_lines(diffFlags);
9271041
ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;
9281042
9291043
/* Prepare the input files */
9301044
memset(&c, 0, sizeof(c));
@@ -941,10 +1055,11 @@
9411055
return 0;
9421056
}
9431057
9441058
/* Compute the difference */
9451059
diff_all(&c);
1060
+ if( (diffFlags & DIFF_NOOPT)==0 ) diff_optimize(&c);
9461061
9471062
if( pOut ){
9481063
/* Compute a context or side-by-side diff into pOut */
9491064
int escHtml = (diffFlags & DIFF_HTML)!=0;
9501065
if( diffFlags & DIFF_SIDEBYSIDE ){
@@ -966,32 +1081,10 @@
9661081
free(c.aTo);
9671082
return c.aEdit;
9681083
}
9691084
}
9701085
971
-/*
972
-** COMMAND: test-rawdiff
973
-*/
974
-void test_rawdiff_cmd(void){
975
- Blob a, b;
976
- int r;
977
- int i;
978
- int *R;
979
- if( g.argc<4 ) usage("FILE1 FILE2 ...");
980
- blob_read_from_file(&a, g.argv[2]);
981
- for(i=3; i<g.argc; i++){
982
- if( i>3 ) fossil_print("-------------------------------\n");
983
- blob_read_from_file(&b, g.argv[i]);
984
- R = text_diff(&a, &b, 0, 0);
985
- for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
986
- fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
987
- }
988
- /* free(R); */
989
- blob_reset(&b);
990
- }
991
-}
992
-
9931086
/*
9941087
** Process diff-related command-line options and return an appropriate
9951088
** "diffFlags" integer.
9961089
**
9971090
** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE
@@ -1014,12 +1107,37 @@
10141107
if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
10151108
diffFlags |= f;
10161109
}
10171110
if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML;
10181111
if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO;
1112
+ if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT;
1113
+ if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT;
10191114
return diffFlags;
10201115
}
1116
+
1117
+/*
1118
+** COMMAND: test-rawdiff
1119
+*/
1120
+void test_rawdiff_cmd(void){
1121
+ Blob a, b;
1122
+ int r;
1123
+ int i;
1124
+ int *R;
1125
+ int diffFlags = diff_options();
1126
+ if( g.argc<4 ) usage("FILE1 FILE2 ...");
1127
+ blob_read_from_file(&a, g.argv[2]);
1128
+ for(i=3; i<g.argc; i++){
1129
+ if( i>3 ) fossil_print("-------------------------------\n");
1130
+ blob_read_from_file(&b, g.argv[i]);
1131
+ R = text_diff(&a, &b, 0, diffFlags);
1132
+ for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
1133
+ fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
1134
+ }
1135
+ /* free(R); */
1136
+ blob_reset(&b);
1137
+ }
1138
+}
10211139
10221140
/*
10231141
** COMMAND: test-udiff
10241142
**
10251143
** Print the difference between two files. The usual diff options apply.
10261144
--- src/diff.c
+++ src/diff.c
@@ -33,10 +33,12 @@
33 #define DIFF_SIDEBYSIDE 0x02000000 /* Generate a side-by-side diff */
34 #define DIFF_NEWFILE 0x04000000 /* Missing files are as empty files */
35 #define DIFF_INLINE 0x08000000 /* Inline (not side-by-side) diff */
36 #define DIFF_HTML 0x10000000 /* Render for HTML */
37 #define DIFF_LINENO 0x20000000 /* Show line numbers in context diff */
 
 
38
39 #endif /* INTERFACE */
40
41 /*
42 ** Maximum length of a line in a text file. (8192)
@@ -61,10 +63,15 @@
61 ** above are one per line of input text. But each entry is also
62 ** a bucket in a hash table, as follows: */
63 unsigned int iHash; /* 1+(first entry in the hash chain) */
64 };
65
 
 
 
 
 
66 /*
67 ** A context for running a raw diff.
68 **
69 ** The aEdit[] array describes the raw diff. Each triple of integers in
70 ** aEdit[] means:
@@ -876,10 +883,112 @@
876 p->aEdit[p->nEdit++] = 0;
877 p->aEdit[p->nEdit++] = 0;
878 p->aEdit[p->nEdit++] = 0;
879 }
880 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
881
882 /*
883 ** Extract the number of lines of context from diffFlags. Supply an
884 ** appropriate default if no context width is specified.
885 */
@@ -921,10 +1030,15 @@
921 ){
922 int ignoreEolWs; /* Ignore whitespace at the end of lines */
923 int nContext; /* Amount of context to display */
924 DContext c;
925
 
 
 
 
 
926 nContext = diff_context_lines(diffFlags);
927 ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;
928
929 /* Prepare the input files */
930 memset(&c, 0, sizeof(c));
@@ -941,10 +1055,11 @@
941 return 0;
942 }
943
944 /* Compute the difference */
945 diff_all(&c);
 
946
947 if( pOut ){
948 /* Compute a context or side-by-side diff into pOut */
949 int escHtml = (diffFlags & DIFF_HTML)!=0;
950 if( diffFlags & DIFF_SIDEBYSIDE ){
@@ -966,32 +1081,10 @@
966 free(c.aTo);
967 return c.aEdit;
968 }
969 }
970
971 /*
972 ** COMMAND: test-rawdiff
973 */
974 void test_rawdiff_cmd(void){
975 Blob a, b;
976 int r;
977 int i;
978 int *R;
979 if( g.argc<4 ) usage("FILE1 FILE2 ...");
980 blob_read_from_file(&a, g.argv[2]);
981 for(i=3; i<g.argc; i++){
982 if( i>3 ) fossil_print("-------------------------------\n");
983 blob_read_from_file(&b, g.argv[i]);
984 R = text_diff(&a, &b, 0, 0);
985 for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
986 fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
987 }
988 /* free(R); */
989 blob_reset(&b);
990 }
991 }
992
993 /*
994 ** Process diff-related command-line options and return an appropriate
995 ** "diffFlags" integer.
996 **
997 ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE
@@ -1014,12 +1107,37 @@
1014 if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
1015 diffFlags |= f;
1016 }
1017 if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML;
1018 if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO;
 
 
1019 return diffFlags;
1020 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1021
1022 /*
1023 ** COMMAND: test-udiff
1024 **
1025 ** Print the difference between two files. The usual diff options apply.
1026
--- src/diff.c
+++ src/diff.c
@@ -33,10 +33,12 @@
33 #define DIFF_SIDEBYSIDE 0x02000000 /* Generate a side-by-side diff */
34 #define DIFF_NEWFILE 0x04000000 /* Missing files are as empty files */
35 #define DIFF_INLINE 0x08000000 /* Inline (not side-by-side) diff */
36 #define DIFF_HTML 0x10000000 /* Render for HTML */
37 #define DIFF_LINENO 0x20000000 /* Show line numbers in context diff */
38 #define DIFF_NOOPT 0x40000000 /* Suppress optimizations for debug */
39 #define DIFF_INVERT 0x80000000 /* Invert the diff for debug */
40
41 #endif /* INTERFACE */
42
43 /*
44 ** Maximum length of a line in a text file. (8192)
@@ -61,10 +63,15 @@
63 ** above are one per line of input text. But each entry is also
64 ** a bucket in a hash table, as follows: */
65 unsigned int iHash; /* 1+(first entry in the hash chain) */
66 };
67
68 /*
69 ** Length of a dline
70 */
71 #define LENGTH(X) ((X)->h & LENGTH_MASK)
72
73 /*
74 ** A context for running a raw diff.
75 **
76 ** The aEdit[] array describes the raw diff. Each triple of integers in
77 ** aEdit[] means:
@@ -876,10 +883,112 @@
883 p->aEdit[p->nEdit++] = 0;
884 p->aEdit[p->nEdit++] = 0;
885 p->aEdit[p->nEdit++] = 0;
886 }
887 }
888
889 /*
890 ** Attempt to shift insertion or deletion blocks so that they begin and
891 ** end on lines that are pure whitespace. In other words, try to transform
892 ** this:
893 **
894 ** int func1(int x){
895 ** return x*10;
896 ** +}
897 ** +
898 ** +int func2(int x){
899 ** + return x*20;
900 ** }
901 **
902 ** int func3(int x){
903 ** return x/5;
904 ** }
905 **
906 ** Into one of these:
907 **
908 ** int func1(int x){ int func1(int x){
909 ** return x*10; return x*10;
910 ** } }
911 ** +
912 ** +int func2(int x){ +int func2(int x){
913 ** + return x*20; + return x*20;
914 ** +} +}
915 ** +
916 ** int func3(int x){ int func3(int x){
917 ** return x/5; return x/5;
918 ** } }
919 */
920 static void diff_optimize(DContext *p){
921 int r; /* Index of current triple */
922 int lnFrom; /* Line number in p->aFrom */
923 int lnTo; /* Line number in p->aTo */
924 int cpy, del, ins;
925
926 lnFrom = lnTo = 0;
927 for(r=0; r<p->nEdit; r += 3){
928 cpy = p->aEdit[r];
929 del = p->aEdit[r+1];
930 ins = p->aEdit[r+2];
931 lnFrom += cpy;
932 lnTo += cpy;
933
934 /* Shift insertions toward the beginning of the file */
935 while( cpy>0 && del==0 && ins>0 ){
936 DLine *pTop = &p->aFrom[lnFrom-1]; /* Line before start of insert */
937 DLine *pBtm = &p->aTo[lnTo+ins-1]; /* Last line inserted */
938 if( same_dline(pTop, pBtm)==0 ) break;
939 if( LENGTH(pTop+1)+LENGTH(pBtm)<=LENGTH(pTop)+LENGTH(pBtm-1) ) break;
940 lnFrom--;
941 lnTo--;
942 p->aEdit[r]--;
943 p->aEdit[r+3]++;
944 cpy--;
945 }
946
947 /* Shift insertions toward the end of the file */
948 while( p->aEdit[r+3]>0 && del==0 && ins>0 ){
949 DLine *pTop = &p->aTo[lnTo]; /* First line inserted */
950 DLine *pBtm = &p->aTo[lnTo+ins]; /* First line past end of insert */
951 if( same_dline(pTop, pBtm)==0 ) break;
952 if( LENGTH(pTop)+LENGTH(pBtm-1)<=LENGTH(pTop+1)+LENGTH(pBtm) ) break;
953 lnFrom++;
954 lnTo++;
955 p->aEdit[r]++;
956 p->aEdit[r+3]--;
957 cpy++;
958 }
959
960 /* Shift deletions toward the beginning of the file */
961 while( cpy>0 && del>0 && ins==0 ){
962 DLine *pTop = &p->aFrom[lnFrom-1]; /* Line before start of delete */
963 DLine *pBtm = &p->aFrom[lnFrom+del-1]; /* Last line deleted */
964 if( same_dline(pTop, pBtm)==0 ) break;
965 if( LENGTH(pTop+1)+LENGTH(pBtm)<=LENGTH(pTop)+LENGTH(pBtm-1) ) break;
966 lnFrom--;
967 lnTo--;
968 p->aEdit[r]--;
969 p->aEdit[r+3]++;
970 cpy--;
971 }
972
973 /* Shift deletions toward the end of the file */
974 while( p->aEdit[r+3]>0 && del>0 && ins==0 ){
975 DLine *pTop = &p->aFrom[lnFrom]; /* First line deleted */
976 DLine *pBtm = &p->aFrom[lnFrom+del]; /* First line past end of delete */
977 if( same_dline(pTop, pBtm)==0 ) break;
978 if( LENGTH(pTop)+LENGTH(pBtm-1)<=LENGTH(pTop)+LENGTH(pBtm) ) break;
979 lnFrom++;
980 lnTo++;
981 p->aEdit[r]++;
982 p->aEdit[r+3]--;
983 cpy++;
984 }
985
986 lnFrom += del;
987 lnTo += ins;
988 }
989 }
990
991 /*
992 ** Extract the number of lines of context from diffFlags. Supply an
993 ** appropriate default if no context width is specified.
994 */
@@ -921,10 +1030,15 @@
1030 ){
1031 int ignoreEolWs; /* Ignore whitespace at the end of lines */
1032 int nContext; /* Amount of context to display */
1033 DContext c;
1034
1035 if( diffFlags & DIFF_INVERT ){
1036 Blob *pTemp = pA_Blob;
1037 pA_Blob = pB_Blob;
1038 pB_Blob = pTemp;
1039 }
1040 nContext = diff_context_lines(diffFlags);
1041 ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;
1042
1043 /* Prepare the input files */
1044 memset(&c, 0, sizeof(c));
@@ -941,10 +1055,11 @@
1055 return 0;
1056 }
1057
1058 /* Compute the difference */
1059 diff_all(&c);
1060 if( (diffFlags & DIFF_NOOPT)==0 ) diff_optimize(&c);
1061
1062 if( pOut ){
1063 /* Compute a context or side-by-side diff into pOut */
1064 int escHtml = (diffFlags & DIFF_HTML)!=0;
1065 if( diffFlags & DIFF_SIDEBYSIDE ){
@@ -966,32 +1081,10 @@
1081 free(c.aTo);
1082 return c.aEdit;
1083 }
1084 }
1085
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1086 /*
1087 ** Process diff-related command-line options and return an appropriate
1088 ** "diffFlags" integer.
1089 **
1090 ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE
@@ -1014,12 +1107,37 @@
1107 if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
1108 diffFlags |= f;
1109 }
1110 if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML;
1111 if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO;
1112 if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT;
1113 if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT;
1114 return diffFlags;
1115 }
1116
1117 /*
1118 ** COMMAND: test-rawdiff
1119 */
1120 void test_rawdiff_cmd(void){
1121 Blob a, b;
1122 int r;
1123 int i;
1124 int *R;
1125 int diffFlags = diff_options();
1126 if( g.argc<4 ) usage("FILE1 FILE2 ...");
1127 blob_read_from_file(&a, g.argv[2]);
1128 for(i=3; i<g.argc; i++){
1129 if( i>3 ) fossil_print("-------------------------------\n");
1130 blob_read_from_file(&b, g.argv[i]);
1131 R = text_diff(&a, &b, 0, diffFlags);
1132 for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
1133 fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
1134 }
1135 /* free(R); */
1136 blob_reset(&b);
1137 }
1138 }
1139
1140 /*
1141 ** COMMAND: test-udiff
1142 **
1143 ** Print the difference between two files. The usual diff options apply.
1144
+3
--- src/info.c
+++ src/info.c
@@ -373,10 +373,13 @@
373373
374374
/* "dc" query parameter determines lines of context */
375375
x = atoi(PD("dc","7"));
376376
if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK;
377377
diffFlags += x;
378
+
379
+ /* The "noopt" parameter disables diff optimization */
380
+ if( PD("noopt",0)!=0 ) diffFlags |= DIFF_NOOPT;
378381
}
379382
return diffFlags;
380383
}
381384
382385
383386
--- src/info.c
+++ src/info.c
@@ -373,10 +373,13 @@
373
374 /* "dc" query parameter determines lines of context */
375 x = atoi(PD("dc","7"));
376 if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK;
377 diffFlags += x;
 
 
 
378 }
379 return diffFlags;
380 }
381
382
383
--- src/info.c
+++ src/info.c
@@ -373,10 +373,13 @@
373
374 /* "dc" query parameter determines lines of context */
375 x = atoi(PD("dc","7"));
376 if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK;
377 diffFlags += x;
378
379 /* The "noopt" parameter disables diff optimization */
380 if( PD("noopt",0)!=0 ) diffFlags |= DIFF_NOOPT;
381 }
382 return diffFlags;
383 }
384
385
386

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button