diff --git a/src/viewer/hex.c b/src/viewer/hex.c
index e355cfb..608bf94 100644
a
|
b
|
static const char hex_char[] = "0123456789ABCDEF"; |
73 | 73 | /*** file scope functions ************************************************************************/ |
74 | 74 | /* --------------------------------------------------------------------------------------------- */ |
75 | 75 | |
76 | | #ifdef HAVE_CHARSET |
77 | | static int |
78 | | utf8_to_int (char *str, int *char_width, gboolean * result) |
79 | | { |
80 | | int res = -1; |
81 | | gunichar ch; |
82 | | gchar *next_ch = NULL; |
83 | | int width = 0; |
84 | | |
85 | | *result = TRUE; |
86 | | |
87 | | if (str == NULL) |
88 | | { |
89 | | *result = FALSE; |
90 | | return 0; |
91 | | } |
92 | | |
93 | | res = g_utf8_get_char_validated (str, -1); |
94 | | |
95 | | if (res < 0) |
96 | | ch = *str; |
97 | | else |
98 | | { |
99 | | ch = res; |
100 | | /* Calculate UTF-8 char width */ |
101 | | next_ch = g_utf8_next_char (str); |
102 | | if (next_ch) |
103 | | width = next_ch - str; |
104 | | else |
105 | | ch = 0; |
106 | | } |
107 | | *char_width = width; |
108 | | return ch; |
109 | | } |
110 | | #endif /* HAVE_CHARSET */ |
111 | | |
112 | 76 | /* --------------------------------------------------------------------------------------------- */ |
113 | 77 | /** Determine the state of the current byte. |
114 | 78 | * |
… |
… |
utf8_to_int (char *str, int *char_width, gboolean * result) |
118 | 82 | */ |
119 | 83 | |
120 | 84 | static mark_t |
121 | | mcview_hex_calculate_boldflag (mcview_t * view, off_t from, struct hexedit_change_node *curr) |
| 85 | mcview_hex_calculate_boldflag (mcview_t * view, off_t from, struct hexedit_change_node *curr, |
| 86 | gboolean force_changed) |
122 | 87 | { |
123 | 88 | return (from == view->hex_cursor) ? MARK_CURSOR |
124 | | : (curr != NULL && from == curr->offset) ? MARK_CHANGED |
| 89 | : ((curr != NULL && from == curr->offset) || force_changed) ? MARK_CHANGED |
125 | 90 | : (view->search_start <= from && from < view->search_end) ? MARK_SELECTED : MARK_NORMAL; |
126 | 91 | } |
127 | 92 | |
… |
… |
mcview_display_hex (mcview_t * view) |
146 | 111 | const screen_dimen text_start = 8 + 13 * ngroups + |
147 | 112 | ((width < 80) ? 0 : (width == 80) ? (ngroups - 1) : (ngroups - 1 + 1)); |
148 | 113 | |
149 | | screen_dimen row; |
| 114 | int row; |
150 | 115 | off_t from; |
151 | 116 | int c; |
152 | | mark_t boldflag = MARK_NORMAL; |
| 117 | mark_t boldflag_byte = MARK_NORMAL, boldflag_char = MARK_NORMAL; |
153 | 118 | struct hexedit_change_node *curr = view->change_list; |
154 | 119 | #ifdef HAVE_CHARSET |
155 | 120 | int ch = 0; |
| 121 | int cont_bytes = 0; /* number of continuation bytes remanining from current UTF-8 */ |
| 122 | gboolean cjk_right = FALSE; /* whether the second byte of a CJK is to be processed */ |
156 | 123 | #endif /* HAVE_CHARSET */ |
| 124 | gboolean utf8_changed = FALSE; /* whether any of the bytes in the UTF-8 were changed */ |
157 | 125 | |
158 | 126 | char hex_buff[10]; /* A temporary buffer for sprintf and mvwaddstr */ |
159 | 127 | int bytes; /* Number of bytes already printed on the line */ |
… |
… |
mcview_display_hex (mcview_t * view) |
161 | 129 | mcview_display_clean (view); |
162 | 130 | |
163 | 131 | /* Find the first displayable changed byte */ |
| 132 | /* In UTF-8 mode, go back by 1 or maybe 2 lines to handle continuation bytes properly. */ |
164 | 133 | from = view->dpy_start; |
| 134 | row = 0; |
| 135 | #ifdef HAVE_CHARSET |
| 136 | if (view->utf8) |
| 137 | { |
| 138 | if (from >= view->bytes_per_line) { |
| 139 | row--; |
| 140 | from -= view->bytes_per_line; |
| 141 | } |
| 142 | if (view->bytes_per_line == 4 && from >= view->bytes_per_line) { |
| 143 | row--; |
| 144 | from -= view->bytes_per_line; |
| 145 | } |
| 146 | } |
| 147 | #endif /* HAVE_CHARSET */ |
165 | 148 | while (curr && (curr->offset < from)) |
166 | 149 | { |
167 | 150 | curr = curr->next; |
168 | 151 | } |
169 | 152 | |
170 | | for (row = 0; mcview_get_byte (view, from, NULL) == TRUE && row < height; row++) |
| 153 | for (; mcview_get_byte (view, from, NULL) == TRUE && row < (int) height; row++) |
171 | 154 | { |
172 | 155 | screen_dimen col = 0; |
173 | 156 | size_t i; |
… |
… |
mcview_display_hex (mcview_t * view) |
175 | 158 | col = 0; |
176 | 159 | |
177 | 160 | /* Print the hex offset */ |
178 | | g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from); |
179 | | widget_move (view, top + row, left); |
180 | | tty_setcolor (VIEW_BOLD_COLOR); |
181 | | for (i = 0; col < width && hex_buff[i] != '\0'; i++) |
182 | | { |
183 | | tty_print_char (hex_buff[i]); |
184 | | /* tty_print_char(hex_buff[i]); */ |
185 | | col += 1; |
| 161 | if (row >= 0) { |
| 162 | g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from); |
| 163 | widget_move (view, top + row, left); |
| 164 | tty_setcolor (VIEW_BOLD_COLOR); |
| 165 | for (i = 0; col < width && hex_buff[i] != '\0'; i++) |
| 166 | { |
| 167 | tty_print_char (hex_buff[i]); |
| 168 | col += 1; |
| 169 | } |
| 170 | tty_setcolor (VIEW_NORMAL_COLOR); |
186 | 171 | } |
187 | | tty_setcolor (VIEW_NORMAL_COLOR); |
188 | 172 | |
189 | 173 | for (bytes = 0; bytes < view->bytes_per_line; bytes++, from++) |
190 | 174 | { |
… |
… |
mcview_display_hex (mcview_t * view) |
192 | 176 | #ifdef HAVE_CHARSET |
193 | 177 | if (view->utf8) |
194 | 178 | { |
195 | | int cw = 1; |
196 | | gboolean read_res = TRUE; |
197 | | |
198 | | ch = mcview_get_utf (view, from, &cw, &read_res); |
199 | | if (!read_res) |
200 | | break; |
201 | | /* char width is greater 0 bytes */ |
202 | | if (cw != 0) |
203 | | { |
204 | | int cnt; |
205 | | char corr_buf[UTF8_CHAR_LEN + 1]; |
206 | | struct hexedit_change_node *corr = curr; |
207 | | int res; |
208 | | |
209 | | res = g_unichar_to_utf8 (ch, (char *) corr_buf); |
210 | | |
211 | | for (cnt = 0; cnt < cw; cnt++) |
212 | | { |
213 | | if (curr != NULL && from + cnt == curr->offset) |
214 | | { |
215 | | /* replace only changed bytes in array of multibyte char */ |
216 | | corr_buf[cnt] = curr->value; |
217 | | curr = curr->next; |
218 | | } |
| 179 | int res; |
| 180 | int j; |
| 181 | struct hexedit_change_node *corr = curr; |
| 182 | gchar utf8buf[UTF8_CHAR_LEN + 1]; |
| 183 | |
| 184 | if (cont_bytes) { |
| 185 | /* UTF-8 continuation bytes, print a space (with proper attributes)... */ |
| 186 | cont_bytes--; |
| 187 | ch = ' '; |
| 188 | if (cjk_right) { |
| 189 | /* ... except when it'd wipe out the right half of a CJK, then print nothing */ |
| 190 | cjk_right = FALSE; |
| 191 | ch = -1; |
219 | 192 | } |
220 | | corr_buf[res] = '\0'; |
221 | | /* Determine the state of the current multibyte char */ |
222 | | ch = utf8_to_int ((char *) corr_buf, &cw, &read_res); |
223 | | curr = corr; |
224 | | } |
| 193 | } else { |
| 194 | int first_changed = -1; |
| 195 | for (j = 0; j < UTF8_CHAR_LEN; j++) { |
| 196 | if (mcview_get_byte (view, from + j, &res)) |
| 197 | utf8buf[j] = res; |
| 198 | else |
| 199 | { |
| 200 | utf8buf[j] = '\0'; |
| 201 | break; |
| 202 | } |
| 203 | if (curr != NULL && from + j == curr->offset) { |
| 204 | utf8buf[j] = curr->value; |
| 205 | if (first_changed == -1) |
| 206 | first_changed = j; |
| 207 | } |
| 208 | if (curr != NULL && from + j >= curr->offset) |
| 209 | curr = curr->next; |
| 210 | } |
| 211 | utf8buf[UTF8_CHAR_LEN] = '\0'; |
| 212 | /* Determine the state of the current multibyte char */ |
| 213 | ch = g_utf8_get_char_validated (utf8buf, -1); |
| 214 | if (ch == -1 || ch == -2) { |
| 215 | ch = '.'; |
| 216 | } else { |
| 217 | gchar *next_ch = g_utf8_next_char (utf8buf); |
| 218 | cont_bytes = next_ch - utf8buf - 1; |
| 219 | if (g_unichar_iswide(ch)) |
| 220 | cjk_right = TRUE; |
| 221 | } |
| 222 | utf8_changed = (first_changed >= 0 && first_changed <= cont_bytes); |
| 223 | curr = corr; |
| 224 | } |
225 | 225 | } |
226 | 226 | #endif /* HAVE_CHARSET */ |
| 227 | |
| 228 | /* For negative rows, the only thing we care about is overflowing |
| 229 | * UTF-8 continuation bytes which were handled above. */ |
| 230 | if (row < 0) |
| 231 | { |
| 232 | if (curr != NULL && from == curr->offset) |
| 233 | curr = curr->next; |
| 234 | continue; |
| 235 | } |
| 236 | |
227 | 237 | if (!mcview_get_byte (view, from, &c)) |
228 | 238 | break; |
229 | 239 | |
… |
… |
mcview_display_hex (mcview_t * view) |
235 | 245 | } |
236 | 246 | |
237 | 247 | /* Determine the state of the current byte */ |
238 | | boldflag = mcview_hex_calculate_boldflag (view, from, curr); |
| 248 | boldflag_byte = mcview_hex_calculate_boldflag (view, from, curr, FALSE); |
| 249 | boldflag_char = mcview_hex_calculate_boldflag (view, from, curr, utf8_changed); |
239 | 250 | |
240 | 251 | /* Determine the value of the current byte */ |
241 | 252 | if (curr != NULL && from == curr->offset) |
… |
… |
mcview_display_hex (mcview_t * view) |
245 | 256 | } |
246 | 257 | |
247 | 258 | /* Select the color for the hex number */ |
248 | | tty_setcolor (boldflag == MARK_NORMAL ? VIEW_NORMAL_COLOR : |
249 | | boldflag == MARK_SELECTED ? VIEW_BOLD_COLOR : |
250 | | boldflag == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : |
251 | | /* boldflag == MARK_CURSOR */ |
| 259 | tty_setcolor (boldflag_byte == MARK_NORMAL ? VIEW_NORMAL_COLOR : |
| 260 | boldflag_byte == MARK_SELECTED ? VIEW_BOLD_COLOR : |
| 261 | boldflag_byte == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : |
| 262 | /* boldflag_byte == MARK_CURSOR */ |
252 | 263 | view->hexview_in_text ? VIEW_SELECTED_COLOR : VIEW_UNDERLINED_COLOR); |
253 | 264 | |
254 | 265 | /* Print the hex number */ |
… |
… |
mcview_display_hex (mcview_t * view) |
292 | 303 | |
293 | 304 | /* Select the color for the character; this differs from the |
294 | 305 | * hex color when boldflag == MARK_CURSOR */ |
295 | | tty_setcolor (boldflag == MARK_NORMAL ? VIEW_NORMAL_COLOR : |
296 | | boldflag == MARK_SELECTED ? VIEW_BOLD_COLOR : |
297 | | boldflag == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : |
298 | | /* boldflag == MARK_CURSOR */ |
| 306 | tty_setcolor (boldflag_char == MARK_NORMAL ? VIEW_NORMAL_COLOR : |
| 307 | boldflag_char == MARK_SELECTED ? VIEW_BOLD_COLOR : |
| 308 | boldflag_char == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : |
| 309 | /* boldflag_char == MARK_CURSOR */ |
299 | 310 | view->hexview_in_text ? VIEW_SELECTED_COLOR : MARKED_SELECTED_COLOR); |
300 | 311 | |
301 | 312 | |