diff --git a/src/viewer/hex.c b/src/viewer/hex.c
index e355cfb..78e9c90 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 | * |
… |
… |
mcview_display_hex (mcview_t * view) |
146 | 110 | const screen_dimen text_start = 8 + 13 * ngroups + |
147 | 111 | ((width < 80) ? 0 : (width == 80) ? (ngroups - 1) : (ngroups - 1 + 1)); |
148 | 112 | |
149 | | screen_dimen row; |
| 113 | int row; |
150 | 114 | off_t from; |
151 | 115 | int c; |
152 | 116 | mark_t boldflag = MARK_NORMAL; |
153 | 117 | struct hexedit_change_node *curr = view->change_list; |
154 | 118 | #ifdef HAVE_CHARSET |
155 | 119 | int ch = 0; |
| 120 | int cont_bytes = 0; /* number of continuation bytes remanining from current UTF-8 */ |
| 121 | gboolean cjk_right = FALSE; /* whether the second byte of a CJK is to be processed */ |
156 | 122 | #endif /* HAVE_CHARSET */ |
157 | 123 | |
158 | 124 | char hex_buff[10]; /* A temporary buffer for sprintf and mvwaddstr */ |
… |
… |
mcview_display_hex (mcview_t * view) |
161 | 127 | mcview_display_clean (view); |
162 | 128 | |
163 | 129 | /* Find the first displayable changed byte */ |
| 130 | /* In UTF-8 mode, go back by 1 or maybe 2 lines to handle continuation bytes properly. */ |
164 | 131 | from = view->dpy_start; |
| 132 | row = 0; |
| 133 | #ifdef HAVE_CHARSET |
| 134 | if (view->utf8) |
| 135 | { |
| 136 | if (from >= view->bytes_per_line) { |
| 137 | row--; |
| 138 | from -= view->bytes_per_line; |
| 139 | } |
| 140 | if (view->bytes_per_line == 4 && from >= view->bytes_per_line) { |
| 141 | row--; |
| 142 | from -= view->bytes_per_line; |
| 143 | } |
| 144 | } |
| 145 | #endif /* HAVE_CHARSET */ |
165 | 146 | while (curr && (curr->offset < from)) |
166 | 147 | { |
167 | 148 | curr = curr->next; |
168 | 149 | } |
169 | 150 | |
170 | | for (row = 0; mcview_get_byte (view, from, NULL) == TRUE && row < height; row++) |
| 151 | for (; mcview_get_byte (view, from, NULL) == TRUE && row < (int) height; row++) |
171 | 152 | { |
172 | 153 | screen_dimen col = 0; |
173 | 154 | size_t i; |
… |
… |
mcview_display_hex (mcview_t * view) |
175 | 156 | col = 0; |
176 | 157 | |
177 | 158 | /* 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; |
| 159 | if (row >= 0) { |
| 160 | g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from); |
| 161 | widget_move (view, top + row, left); |
| 162 | tty_setcolor (VIEW_BOLD_COLOR); |
| 163 | for (i = 0; col < width && hex_buff[i] != '\0'; i++) |
| 164 | { |
| 165 | tty_print_char (hex_buff[i]); |
| 166 | col += 1; |
| 167 | } |
| 168 | tty_setcolor (VIEW_NORMAL_COLOR); |
186 | 169 | } |
187 | | tty_setcolor (VIEW_NORMAL_COLOR); |
188 | 170 | |
189 | 171 | for (bytes = 0; bytes < view->bytes_per_line; bytes++, from++) |
190 | 172 | { |
… |
… |
mcview_display_hex (mcview_t * view) |
192 | 174 | #ifdef HAVE_CHARSET |
193 | 175 | if (view->utf8) |
194 | 176 | { |
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 | | } |
| 177 | int res; |
| 178 | int j; |
| 179 | struct hexedit_change_node *corr = curr; |
| 180 | gchar utf8buf[UTF8_CHAR_LEN + 1]; |
| 181 | |
| 182 | if (cont_bytes) { |
| 183 | /* UTF-8 continuation bytes, print a space (with proper attributes)... */ |
| 184 | cont_bytes--; |
| 185 | ch = ' '; |
| 186 | if (cjk_right) { |
| 187 | /* ... except when it'd wipe out the right half of a CJK, then print nothing */ |
| 188 | cjk_right = FALSE; |
| 189 | ch = -1; |
219 | 190 | } |
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 | | } |
| 191 | } else { |
| 192 | for (j = 0; j < UTF8_CHAR_LEN; j++) { |
| 193 | if (mcview_get_byte (view, from + j, &res)) |
| 194 | utf8buf[j] = res; |
| 195 | else |
| 196 | { |
| 197 | utf8buf[j] = '\0'; |
| 198 | break; |
| 199 | } |
| 200 | if (curr != NULL && from + j == curr->offset) |
| 201 | utf8buf[j] = curr->value; |
| 202 | if (curr != NULL && from + j >= curr->offset) |
| 203 | curr = curr->next; |
| 204 | } |
| 205 | utf8buf[UTF8_CHAR_LEN] = '\0'; |
| 206 | /* Determine the state of the current multibyte char */ |
| 207 | ch = g_utf8_get_char_validated (utf8buf, -1); |
| 208 | if (ch == -1 || ch == -2) { |
| 209 | ch = '.'; |
| 210 | } else { |
| 211 | gchar *next_ch = g_utf8_next_char (utf8buf); |
| 212 | cont_bytes = next_ch - utf8buf - 1; |
| 213 | if (g_unichar_iswide(ch)) |
| 214 | cjk_right = TRUE; |
| 215 | } |
| 216 | curr = corr; |
| 217 | } |
225 | 218 | } |
226 | 219 | #endif /* HAVE_CHARSET */ |
| 220 | |
| 221 | /* For negative rows, the only thing we care about is overflowing |
| 222 | * UTF-8 continuation bytes which were handled above. */ |
| 223 | if (row < 0) |
| 224 | { |
| 225 | if (curr != NULL && from == curr->offset) |
| 226 | curr = curr->next; |
| 227 | continue; |
| 228 | } |
| 229 | |
227 | 230 | if (!mcview_get_byte (view, from, &c)) |
228 | 231 | break; |
229 | 232 | |