Fossil SCM
Fix a bug in wiki rendering that caused an extra paragraph end tag following a hyperlink.
Commit
8f423ad438265edb43a2e014e4901123bd0930bc
Parent
da9d38e2c38f527…
2 files changed
+78
-5
+1
-1
+78
-5
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -52,10 +52,19 @@ | ||
| 52 | 52 | ** here. |
| 53 | 53 | */ |
| 54 | 54 | static int nField = 0; |
| 55 | 55 | static Blob fieldList; |
| 56 | 56 | static char **azField = 0; |
| 57 | +static char **azValue = 0; | |
| 58 | +static unsigned char *aChanged = 0; | |
| 59 | + | |
| 60 | +/* | |
| 61 | +** Compare two entries in azField for sorting purposes | |
| 62 | +*/ | |
| 63 | +static int nameCmpr(void *a, void *b){ | |
| 64 | + return strcmp((char*)a, (char*)b); | |
| 65 | +} | |
| 57 | 66 | |
| 58 | 67 | /* |
| 59 | 68 | ** Subscript command: LIST setfields |
| 60 | 69 | ** |
| 61 | 70 | ** Parse up the list and populate the nField and azField variables. |
| @@ -70,20 +79,84 @@ | ||
| 70 | 79 | zFieldList = SbS_StackValue(p, 0, &nFieldList); |
| 71 | 80 | blob_appendf(&fieldList, zFieldList, nFieldList); |
| 72 | 81 | while( blob_token(&fieldList, &field) ){ |
| 73 | 82 | nField++; |
| 74 | 83 | } |
| 75 | - azField = malloc( sizeof(azField[0])*nField ); | |
| 76 | - blob_rewind(&fieldList); | |
| 77 | - i = 0; | |
| 78 | - while( blob_token(&fieldList, &field) ){ | |
| 79 | - azField[i] = blob_terminate(&field); | |
| 84 | + azField = malloc( sizeof(azField[0])*nField*2 + nField ); | |
| 85 | + if( azField ){ | |
| 86 | + azValue = &azField[nField]; | |
| 87 | + aChanged = (unsigned char*)&azValue[nField]; | |
| 88 | + blob_rewind(&fieldList); | |
| 89 | + i = 0; | |
| 90 | + while( blob_token(&fieldList, &field) ){ | |
| 91 | + azField[i] = blob_terminate(&field); | |
| 92 | + azValue[i] = 0; | |
| 93 | + aChanged[i] = 0; | |
| 94 | + } | |
| 80 | 95 | } |
| 96 | + qsort(azField, nField, sizeof(azField[0]), nameCmpr); | |
| 81 | 97 | } |
| 82 | 98 | SbS_Pop(p, 1); |
| 83 | 99 | return 0; |
| 84 | 100 | } |
| 101 | + | |
| 102 | +/* | |
| 103 | +** Find the text of the field whose name is the Nth element down | |
| 104 | +** on the Subscript stack. 0 means the top of the stack. | |
| 105 | +** | |
| 106 | +** First check for a value for this field as passed in via | |
| 107 | +** CGI parameter. If not found, then use the value from the | |
| 108 | +** database. | |
| 109 | +*/ | |
| 110 | +static const char *field_value(int N){ | |
| 111 | + const char *zFName; | |
| 112 | + int nFName; | |
| 113 | + char *zName; | |
| 114 | + int i; | |
| 115 | + const char *zValue; | |
| 116 | + | |
| 117 | + zFName = SbS_StackValue(pInterp, N, &nFName); | |
| 118 | + if( zField==0 ){ | |
| 119 | + return 0; | |
| 120 | + } | |
| 121 | + zName = mprintf("%.*s", nFName, zFName); | |
| 122 | + zValue = P(zName); | |
| 123 | + if( zValue==0 ){ | |
| 124 | + for(i=0; i<nField; i++){ | |
| 125 | + if( strcmp(azField[i], zName)==0 ){ | |
| 126 | + zValue = azValue[i]; | |
| 127 | + break; | |
| 128 | + } | |
| 129 | + } | |
| 130 | + } | |
| 131 | + free(zName); | |
| 132 | + return zValue; | |
| 133 | +} | |
| 134 | + | |
| 135 | +/* | |
| 136 | +** Fill in the azValue[] array with the contents of the ticket | |
| 137 | +** table for the entry determined by the "name" CGI parameter. | |
| 138 | +*/ | |
| 139 | +static void fetchOriginalValues(void){ | |
| 140 | + Blob sql; | |
| 141 | + Stmt q; | |
| 142 | + int i; | |
| 143 | + char *zSep = "SELECT "; | |
| 144 | + blob_zero(&sql); | |
| 145 | + for(i=0; i<nField; i++){ | |
| 146 | + blob_appendf(&sql, "%s%s", zSep, azField[i]); | |
| 147 | + zSep = ", "; | |
| 148 | + } | |
| 149 | + blob_appendf(" FROM ticket WHERE uuid=%Q", PD("name","")); | |
| 150 | + db_prepare(&q, "%b", &sql); | |
| 151 | + if( db_step(&q)==SQLITE_ROW ){ | |
| 152 | + for(i=0; i<nField; i++){ | |
| 153 | + azValue[i] = db_column_malloc(&q, i); | |
| 154 | + } | |
| 155 | + } | |
| 156 | + db_finalize(&q); | |
| 157 | +} | |
| 85 | 158 | |
| 86 | 159 | /* |
| 87 | 160 | ** Subscript command: INTEGER not INTEGER |
| 88 | 161 | */ |
| 89 | 162 | static int notCmd(struct Subscript *p, void *pNotUsed){ |
| 90 | 163 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -52,10 +52,19 @@ | |
| 52 | ** here. |
| 53 | */ |
| 54 | static int nField = 0; |
| 55 | static Blob fieldList; |
| 56 | static char **azField = 0; |
| 57 | |
| 58 | /* |
| 59 | ** Subscript command: LIST setfields |
| 60 | ** |
| 61 | ** Parse up the list and populate the nField and azField variables. |
| @@ -70,20 +79,84 @@ | |
| 70 | zFieldList = SbS_StackValue(p, 0, &nFieldList); |
| 71 | blob_appendf(&fieldList, zFieldList, nFieldList); |
| 72 | while( blob_token(&fieldList, &field) ){ |
| 73 | nField++; |
| 74 | } |
| 75 | azField = malloc( sizeof(azField[0])*nField ); |
| 76 | blob_rewind(&fieldList); |
| 77 | i = 0; |
| 78 | while( blob_token(&fieldList, &field) ){ |
| 79 | azField[i] = blob_terminate(&field); |
| 80 | } |
| 81 | } |
| 82 | SbS_Pop(p, 1); |
| 83 | return 0; |
| 84 | } |
| 85 | |
| 86 | /* |
| 87 | ** Subscript command: INTEGER not INTEGER |
| 88 | */ |
| 89 | static int notCmd(struct Subscript *p, void *pNotUsed){ |
| 90 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -52,10 +52,19 @@ | |
| 52 | ** here. |
| 53 | */ |
| 54 | static int nField = 0; |
| 55 | static Blob fieldList; |
| 56 | static char **azField = 0; |
| 57 | static char **azValue = 0; |
| 58 | static unsigned char *aChanged = 0; |
| 59 | |
| 60 | /* |
| 61 | ** Compare two entries in azField for sorting purposes |
| 62 | */ |
| 63 | static int nameCmpr(void *a, void *b){ |
| 64 | return strcmp((char*)a, (char*)b); |
| 65 | } |
| 66 | |
| 67 | /* |
| 68 | ** Subscript command: LIST setfields |
| 69 | ** |
| 70 | ** Parse up the list and populate the nField and azField variables. |
| @@ -70,20 +79,84 @@ | |
| 79 | zFieldList = SbS_StackValue(p, 0, &nFieldList); |
| 80 | blob_appendf(&fieldList, zFieldList, nFieldList); |
| 81 | while( blob_token(&fieldList, &field) ){ |
| 82 | nField++; |
| 83 | } |
| 84 | azField = malloc( sizeof(azField[0])*nField*2 + nField ); |
| 85 | if( azField ){ |
| 86 | azValue = &azField[nField]; |
| 87 | aChanged = (unsigned char*)&azValue[nField]; |
| 88 | blob_rewind(&fieldList); |
| 89 | i = 0; |
| 90 | while( blob_token(&fieldList, &field) ){ |
| 91 | azField[i] = blob_terminate(&field); |
| 92 | azValue[i] = 0; |
| 93 | aChanged[i] = 0; |
| 94 | } |
| 95 | } |
| 96 | qsort(azField, nField, sizeof(azField[0]), nameCmpr); |
| 97 | } |
| 98 | SbS_Pop(p, 1); |
| 99 | return 0; |
| 100 | } |
| 101 | |
| 102 | /* |
| 103 | ** Find the text of the field whose name is the Nth element down |
| 104 | ** on the Subscript stack. 0 means the top of the stack. |
| 105 | ** |
| 106 | ** First check for a value for this field as passed in via |
| 107 | ** CGI parameter. If not found, then use the value from the |
| 108 | ** database. |
| 109 | */ |
| 110 | static const char *field_value(int N){ |
| 111 | const char *zFName; |
| 112 | int nFName; |
| 113 | char *zName; |
| 114 | int i; |
| 115 | const char *zValue; |
| 116 | |
| 117 | zFName = SbS_StackValue(pInterp, N, &nFName); |
| 118 | if( zField==0 ){ |
| 119 | return 0; |
| 120 | } |
| 121 | zName = mprintf("%.*s", nFName, zFName); |
| 122 | zValue = P(zName); |
| 123 | if( zValue==0 ){ |
| 124 | for(i=0; i<nField; i++){ |
| 125 | if( strcmp(azField[i], zName)==0 ){ |
| 126 | zValue = azValue[i]; |
| 127 | break; |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | free(zName); |
| 132 | return zValue; |
| 133 | } |
| 134 | |
| 135 | /* |
| 136 | ** Fill in the azValue[] array with the contents of the ticket |
| 137 | ** table for the entry determined by the "name" CGI parameter. |
| 138 | */ |
| 139 | static void fetchOriginalValues(void){ |
| 140 | Blob sql; |
| 141 | Stmt q; |
| 142 | int i; |
| 143 | char *zSep = "SELECT "; |
| 144 | blob_zero(&sql); |
| 145 | for(i=0; i<nField; i++){ |
| 146 | blob_appendf(&sql, "%s%s", zSep, azField[i]); |
| 147 | zSep = ", "; |
| 148 | } |
| 149 | blob_appendf(" FROM ticket WHERE uuid=%Q", PD("name","")); |
| 150 | db_prepare(&q, "%b", &sql); |
| 151 | if( db_step(&q)==SQLITE_ROW ){ |
| 152 | for(i=0; i<nField; i++){ |
| 153 | azValue[i] = db_column_malloc(&q, i); |
| 154 | } |
| 155 | } |
| 156 | db_finalize(&q); |
| 157 | } |
| 158 | |
| 159 | /* |
| 160 | ** Subscript command: INTEGER not INTEGER |
| 161 | */ |
| 162 | static int notCmd(struct Subscript *p, void *pNotUsed){ |
| 163 |
+1
-1
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -1007,11 +1007,10 @@ | ||
| 1007 | 1007 | break; |
| 1008 | 1008 | } |
| 1009 | 1009 | } |
| 1010 | 1010 | z += n; |
| 1011 | 1011 | } |
| 1012 | - endAutoParagraph(p); | |
| 1013 | 1012 | } |
| 1014 | 1013 | |
| 1015 | 1014 | |
| 1016 | 1015 | /* |
| 1017 | 1016 | ** Transform the text in the pIn blob. Write the results |
| @@ -1033,10 +1032,11 @@ | ||
| 1033 | 1032 | renderer.pOut = cgi_output_blob(); |
| 1034 | 1033 | } |
| 1035 | 1034 | |
| 1036 | 1035 | z = blob_str(pIn); |
| 1037 | 1036 | wiki_render(&renderer, z); |
| 1037 | + endAutoParagraph(&renderer); | |
| 1038 | 1038 | while( renderer.nStack ){ |
| 1039 | 1039 | popStack(&renderer); |
| 1040 | 1040 | } |
| 1041 | 1041 | blob_append(renderer.pOut, "\n", 1); |
| 1042 | 1042 | free(renderer.aStack); |
| 1043 | 1043 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1007,11 +1007,10 @@ | |
| 1007 | break; |
| 1008 | } |
| 1009 | } |
| 1010 | z += n; |
| 1011 | } |
| 1012 | endAutoParagraph(p); |
| 1013 | } |
| 1014 | |
| 1015 | |
| 1016 | /* |
| 1017 | ** Transform the text in the pIn blob. Write the results |
| @@ -1033,10 +1032,11 @@ | |
| 1033 | renderer.pOut = cgi_output_blob(); |
| 1034 | } |
| 1035 | |
| 1036 | z = blob_str(pIn); |
| 1037 | wiki_render(&renderer, z); |
| 1038 | while( renderer.nStack ){ |
| 1039 | popStack(&renderer); |
| 1040 | } |
| 1041 | blob_append(renderer.pOut, "\n", 1); |
| 1042 | free(renderer.aStack); |
| 1043 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1007,11 +1007,10 @@ | |
| 1007 | break; |
| 1008 | } |
| 1009 | } |
| 1010 | z += n; |
| 1011 | } |
| 1012 | } |
| 1013 | |
| 1014 | |
| 1015 | /* |
| 1016 | ** Transform the text in the pIn blob. Write the results |
| @@ -1033,10 +1032,11 @@ | |
| 1032 | renderer.pOut = cgi_output_blob(); |
| 1033 | } |
| 1034 | |
| 1035 | z = blob_str(pIn); |
| 1036 | wiki_render(&renderer, z); |
| 1037 | endAutoParagraph(&renderer); |
| 1038 | while( renderer.nStack ){ |
| 1039 | popStack(&renderer); |
| 1040 | } |
| 1041 | blob_append(renderer.pOut, "\n", 1); |
| 1042 | free(renderer.aStack); |
| 1043 |