static int mcview_char_display (const WView * view, int c, char *s) { #ifdef HAVE_CHARSET if (mc_global.utf8_display) { if (!view->utf8) c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter); if (!g_unichar_isprint (c)) c = '.'; return g_unichar_to_utf8 (c, s); } if (view->utf8) { if (g_unichar_iswide (c)) { s[0] = s[1] = '.'; return 2; } if (g_unichar_iszerowidth (c)) return 0; /* TODO the is_printable check below will be broken for this */ c = convert_from_utf_to_current_c (c, view->converter); } else { /* TODO the is_printable check below will be broken for this */ c = convert_to_display_c (c); } #else (void) view; #endif /* HAVE_CHARSET */ /* TODO this is very-very buggy by design: ticket 3257 comments 0-1 */ if (!is_printable (c)) c = '.'; *s = c; return 1; }
static void edit_draw_this_line (WEdit * edit, long b, long row, long start_col, long end_col) { struct line_s line[MAX_LINE_LEN]; struct line_s *p = line; long m1 = 0, m2 = 0, q, c1, c2; int col, start_col_real; unsigned int c; int color; int abn_style; int i; int utf8lag = 0; unsigned int cur_line = 0; int book_mark = 0; char line_stat[LINE_STATE_WIDTH + 1] = "\0"; if (row > edit->widget.lines - 1 - EDIT_TEXT_VERTICAL_OFFSET) return; if (book_mark_query_color (edit, edit->start_line + row, BOOK_MARK_COLOR)) book_mark = BOOK_MARK_COLOR; else if (book_mark_query_color (edit, edit->start_line + row, BOOK_MARK_FOUND_COLOR)) book_mark = BOOK_MARK_FOUND_COLOR; if (book_mark) abn_style = book_mark << 16; else abn_style = MOD_ABNORMAL; end_col -= EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width; edit_get_syntax_color (edit, b - 1, &color); q = edit_move_forward3 (edit, b, start_col - edit->start_col, 0); start_col_real = (col = (int) edit_move_forward3 (edit, b, 0, q)) + edit->start_col; if (option_line_state) { cur_line = edit->start_line + row; if (cur_line <= (unsigned int) edit->total_lines) { g_snprintf (line_stat, LINE_STATE_WIDTH + 1, "%7i ", cur_line + 1); } else { memset (line_stat, ' ', LINE_STATE_WIDTH); line_stat[LINE_STATE_WIDTH] = '\0'; } if (book_mark_query_color (edit, cur_line, BOOK_MARK_COLOR)) { g_snprintf (line_stat, 2, "*"); } } if (col + 16 > -edit->start_col) { eval_marks (edit, &m1, &m2); if (row <= edit->total_lines - edit->start_line) { long tws = 0; if (tty_use_colors () && visible_tws) { tws = edit_eol (edit, b); while (tws > b && ((c = edit_get_byte (edit, tws - 1)) == ' ' || c == '\t')) tws--; } while (col <= end_col - edit->start_col) { int cw = 1; p->ch = 0; p->style = 0; if (q == edit->curs1) p->style |= MOD_CURSOR; if (q >= m1 && q < m2) { if (edit->column_highlight) { int x; x = edit_move_forward3 (edit, b, 0, q); c1 = min (edit->column1, edit->column2); c2 = max (edit->column1, edit->column2); if (x >= c1 && x < c2) p->style |= MOD_MARKED; } else p->style |= MOD_MARKED; } if (q == edit->bracket) p->style |= MOD_BOLD; if (q >= edit->found_start && q < edit->found_start + edit->found_len) p->style |= MOD_BOLD; if (!edit->utf8) { c = edit_get_byte (edit, q); } else { c = edit_get_utf (edit, q, &cw); } /* we don't use bg for mc - fg contains both */ if (book_mark) { p->style |= book_mark << 16; } else { edit_get_syntax_color (edit, q, &color); p->style |= color << 16; } switch (c) { case '\n': col = (end_col + utf8lag) - edit->start_col + 1; /* quit */ break; case '\t': i = TAB_SIZE - ((int) col % TAB_SIZE); col += i; if (tty_use_colors () && ((visible_tabs || (visible_tws && q >= tws)) && enable_show_tabs_tws)) { if (p->style & MOD_MARKED) c = p->style; else if (book_mark) c |= book_mark << 16; else c = p->style | MOD_WHITESPACE; if (i > 2) { p->ch = '<'; p->style = c; p++; while (--i > 1) { p->ch = '-'; p->style = c; p++; } p->ch = '>'; p->style = c; p++; } else if (i > 1) { p->ch = '<'; p->style = c; p++; p->ch = '>'; p->style = c; p++; } else { p->ch = '>'; p->style = c; p++; } } else if (tty_use_colors () && visible_tws && q >= tws && enable_show_tabs_tws) { p->ch = '.'; p->style |= MOD_WHITESPACE; c = p->style & ~MOD_CURSOR; p++; while (--i) { p->ch = ' '; p->style = c; p++; } } else { p->ch |= ' '; c = p->style & ~MOD_CURSOR; p++; while (--i) { p->ch = ' '; p->style = c; p++; } } break; case ' ': if (tty_use_colors () && visible_tws && q >= tws && enable_show_tabs_tws) { p->ch = '.'; p->style |= MOD_WHITESPACE; p++; col++; break; } /* fallthrough */ default: #ifdef HAVE_CHARSET if (mc_global.utf8_display) { if (!edit->utf8) { c = convert_from_8bit_to_utf_c ((unsigned char) c, edit->converter); } } else if (edit->utf8) c = convert_from_utf_to_current_c (c, edit->converter); else #endif c = convert_to_display_c (c); /* Caret notation for control characters */ if (c < 32) { p->ch = '^'; p->style = abn_style; p++; p->ch = c + 0x40; p->style = abn_style; p++; col += 2; break; } if (c == 127) { p->ch = '^'; p->style = abn_style; p++; p->ch = '?'; p->style = abn_style; p++; col += 2; break; } if (!edit->utf8) { if ((mc_global.utf8_display && g_unichar_isprint (c)) || (!mc_global.utf8_display && is_printable (c))) { p->ch = c; p++; } else { p->ch = '.'; p->style = abn_style; p++; } } else { if (g_unichar_isprint (c)) { p->ch = c; p++; } else { p->ch = '.'; p->style = abn_style; p++; } } col++; break; } /* case */ q++; if (cw > 1) { q += cw - 1; } } } } else { start_col_real = start_col = 0; } p->ch = '\0'; print_to_widget (edit, row, start_col, start_col_real, end_col, line, line_stat, book_mark); }
void mcview_display_hex (mcview_t * view) { const screen_dimen top = view->data_area.top; const screen_dimen left = view->data_area.left; const screen_dimen height = view->data_area.height; const screen_dimen width = view->data_area.width; const int ngroups = view->bytes_per_line / 4; const screen_dimen text_start = 8 + 13 * ngroups + ((width < 80) ? 0 : (ngroups - 1 + 1)); /* 8 characters are used for the file offset, and every hex group * takes 13 characters. On "big" screens, the groups are separated * by an extra vertical line, and there is an extra space before the * text column. */ screen_dimen row; off_t from; int c; mark_t boldflag = MARK_NORMAL; struct hexedit_change_node *curr = view->change_list; #ifdef HAVE_CHARSET int ch = 0; #endif /* HAVE_CHARSET */ char hex_buff[10]; /* A temporary buffer for sprintf and mvwaddstr */ int bytes; /* Number of bytes already printed on the line */ mcview_display_clean (view); /* Find the first displayable changed byte */ from = view->dpy_start; while (curr && (curr->offset < from)) { curr = curr->next; } for (row = 0; mcview_get_byte (view, from, NULL) == TRUE && row < height; row++) { screen_dimen col = 0; size_t i; col = 0; /* Print the hex offset */ g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from); widget_move (view, top + row, left); tty_setcolor (VIEW_BOLD_COLOR); for (i = 0; col < width && hex_buff[i] != '\0'; i++) { tty_print_char (hex_buff[i]); /* tty_print_char(hex_buff[i]); */ col += 1; } tty_setcolor (VIEW_NORMAL_COLOR); for (bytes = 0; bytes < view->bytes_per_line; bytes++, from++) { #ifdef HAVE_CHARSET if (view->utf8) { int cw = 1; gboolean read_res = TRUE; ch = mcview_get_utf (view, from, &cw, &read_res); if (!read_res) break; /* char width is greater 0 bytes */ if (cw != 0) { int cnt; char corr_buf[UTF8_CHAR_LEN + 1]; struct hexedit_change_node *corr = curr; int res; res = g_unichar_to_utf8 (ch, (char *) corr_buf); for (cnt = 0; cnt < cw; cnt++) { if (curr != NULL && from + cnt == curr->offset) { /* replace only changed bytes in array of multibyte char */ corr_buf[cnt] = curr->value; curr = curr->next; } } corr_buf[res] = '\0'; /* Determine the state of the current multibyte char */ ch = utf8_to_int ((char *) corr_buf, &cw, &read_res); curr = corr; } } #endif /* HAVE_CHARSET */ if (!mcview_get_byte (view, from, &c)) break; /* Save the cursor position for mcview_place_cursor() */ if (from == view->hex_cursor && !view->hexview_in_text) { view->cursor_row = row; view->cursor_col = col; } /* Determine the state of the current byte */ boldflag = mcview_hex_calculate_boldflag (view, from, curr); /* Determine the value of the current byte */ if (curr != NULL && from == curr->offset) { c = curr->value; curr = curr->next; } /* Select the color for the hex number */ tty_setcolor (boldflag == MARK_NORMAL ? VIEW_NORMAL_COLOR : boldflag == MARK_SELECTED ? VIEW_BOLD_COLOR : boldflag == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : /* boldflag == MARK_CURSOR */ view->hexview_in_text ? VIEW_SELECTED_COLOR : VIEW_UNDERLINED_COLOR); /* Print the hex number */ widget_move (view, top + row, left + col); if (col < width) { tty_print_char (hex_char[c / 16]); col += 1; } if (col < width) { tty_print_char (hex_char[c % 16]); col += 1; } /* Print the separator */ tty_setcolor (VIEW_NORMAL_COLOR); if (bytes != view->bytes_per_line - 1) { if (col < width) { tty_print_char (' '); col += 1; } /* After every four bytes, print a group separator */ if (bytes % 4 == 3) { if (view->data_area.width >= 80 && col < width) { tty_print_one_vline (TRUE); col += 1; } if (col < width) { tty_print_char (' '); col += 1; } } } /* Select the color for the character; this differs from the * hex color when boldflag == MARK_CURSOR */ tty_setcolor (boldflag == MARK_NORMAL ? VIEW_NORMAL_COLOR : boldflag == MARK_SELECTED ? VIEW_BOLD_COLOR : boldflag == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : /* boldflag == MARK_CURSOR */ view->hexview_in_text ? VIEW_SELECTED_COLOR : MARKED_SELECTED_COLOR); #ifdef HAVE_CHARSET if (mc_global.utf8_display) { if (!view->utf8) { c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter); } if (!g_unichar_isprint (c)) c = '.'; } else if (view->utf8) ch = convert_from_utf_to_current_c (ch, view->converter); else #endif { #ifdef HAVE_CHARSET c = convert_to_display_c (c); #endif if (!is_printable (c)) c = '.'; } /* Print corresponding character on the text side */ if (text_start + bytes < width) { widget_move (view, top + row, left + text_start + bytes); #ifdef HAVE_CHARSET if (view->utf8) tty_print_anychar (ch); else #endif tty_print_char (c); } /* Save the cursor position for mcview_place_cursor() */ if (from == view->hex_cursor && view->hexview_in_text) { view->cursor_row = row; view->cursor_col = text_start + bytes; } } } /* Be polite to the other functions */ tty_setcolor (VIEW_NORMAL_COLOR); mcview_place_cursor (view); view->dpy_end = from; }
void mcview_display_nroff (mcview_t * view) { const screen_dimen left = view->data_area.left; const screen_dimen top = view->data_area.top; const screen_dimen width = view->data_area.width; const screen_dimen height = view->data_area.height; screen_dimen row, col; off_t from; int cw = 1; int c; int c_prev = 0; int c_next = 0; struct hexedit_change_node *curr = view->change_list; mcview_display_clean (view); mcview_display_ruler (view); /* Find the first displayable changed byte */ from = view->dpy_start; while (curr && (curr->offset < from)) { curr = curr->next; } tty_setcolor (NORMAL_COLOR); for (row = 0, col = 0; row < height;) { #ifdef HAVE_CHARSET if (view->utf8) { gboolean read_res = TRUE; c = mcview_get_utf (view, from, &cw, &read_res); if (!read_res) break; } else #endif { if (!mcview_get_byte (view, from, &c)) break; } from++; if (cw > 1) from += cw - 1; if (c == '\b') { if (from > 1) { #ifdef HAVE_CHARSET if (view->utf8) { gboolean read_res; c_next = mcview_get_utf (view, from, &cw, &read_res); } else #endif mcview_get_byte (view, from, &c_next); } if (g_unichar_isprint (c_prev) && g_unichar_isprint (c_next) && (c_prev == c_next || c_prev == '_' || (c_prev == '+' && c_next == 'o'))) { if (col == 0) { if (row == 0) { /* We're inside an nroff character sequence at the * beginning of the screen -- just skip the * backspace and continue with the next character. */ continue; } row--; col = width; } col--; if (c_prev == '_' && (c_next != '_' || mcview_count_backspaces (view, from + 1) == 1)) tty_setcolor (VIEW_UNDERLINED_COLOR); else tty_setcolor (VIEW_BOLD_COLOR); continue; } } if ((c == '\n') || (col >= width && view->text_wrap_mode)) { col = 0; row++; if (c == '\n' || row >= height) continue; } if (c == '\r') { mcview_get_byte_indexed (view, from, 1, &c); if (c == '\r' || c == '\n') continue; col = 0; row++; continue; } if (c == '\t') { off_t line, column; mcview_offset_to_coord (view, &line, &column, from); col += (option_tab_spacing - col % option_tab_spacing); if (view->text_wrap_mode && col >= width && width != 0) { row += col / width; col %= width; } continue; } if (view->search_start <= from && from < view->search_end) { tty_setcolor (SELECTED_COLOR); } c_prev = c; if ((off_t) col >= view->dpy_text_column && (off_t) col - view->dpy_text_column < (off_t) width) { widget_move (view, top + row, left + ((off_t) col - view->dpy_text_column)); #ifdef HAVE_CHARSET if (mc_global.utf8_display) { if (!view->utf8) { c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter); } if (!g_unichar_isprint (c)) c = '.'; } else if (view->utf8) c = convert_from_utf_to_current_c (c, view->converter); else c = convert_to_display_c (c); #endif tty_print_anychar (c); } col++; #ifdef HAVE_CHARSET if (view->utf8) { if (g_unichar_iswide (c)) col++; else if (g_unichar_iszerowidth (c)) col--; } #endif tty_setcolor (NORMAL_COLOR); } view->dpy_end = from; }
void mcview_display_text (mcview_t * view) { const screen_dimen left = view->data_area.left; const screen_dimen top = view->data_area.top; const screen_dimen width = view->data_area.width; const screen_dimen height = view->data_area.height; screen_dimen row = 0, col = 0; off_t from; int cw = 1; int c, prev_ch = 0; gboolean last_row = TRUE; struct hexedit_change_node *curr = view->change_list; mcview_display_clean (view); mcview_display_ruler (view); /* Find the first displayable changed byte */ from = view->dpy_start; while ((curr != NULL) && (curr->offset < from)) curr = curr->next; while (TRUE) { tty_setcolor (NORMAL_COLOR); if (row >= height) break; #ifdef HAVE_CHARSET if (view->utf8) { gboolean read_res = TRUE; c = mcview_get_utf (view, from, &cw, &read_res); if (!read_res) break; } else #endif if (!mcview_get_byte (view, from, &c)) break; last_row = FALSE; from++; if (cw > 1) from += cw - 1; if (c != '\n' && prev_ch == '\r') { if (++row >= height) break; col = 0; /* tty_print_anychar ('\n'); */ } prev_ch = c; if (c == '\r') continue; if (c == '\n') { col = 0; row++; continue; } if (col >= width && view->text_wrap_mode) { col = 0; if (++row >= height) break; } if (c == '\t') { col += (option_tab_spacing - col % option_tab_spacing); if (view->text_wrap_mode && col >= width && width != 0) { row += col / width; col %= width; } continue; } if (view->search_start <= from && from < view->search_end) tty_setcolor (SELECTED_COLOR); if (((off_t) col >= view->dpy_text_column) && ((off_t) col - view->dpy_text_column < (off_t) width)) { widget_move (view, top + row, left + ((off_t) col - view->dpy_text_column)); #ifdef HAVE_CHARSET if (mc_global.utf8_display) { if (!view->utf8) c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter); if (!g_unichar_isprint (c)) c = '.'; } else if (view->utf8) c = convert_from_utf_to_current_c (c, view->converter); else #endif { #ifdef HAVE_CHARSET c = convert_to_display_c (c); #endif if (!is_printable (c)) c = '.'; } tty_print_anychar (c); } col++; #ifdef HAVE_CHARSET if (view->utf8) { if (g_unichar_iswide (c)) col++; else if (g_unichar_iszerowidth (c)) col--; } #endif } view->dpy_end = from; if (mcview_show_eof != NULL && mcview_show_eof[0] != '\0') { if (last_row && mcview_get_byte (view, from - 1, &c)) if (c != '\n') row--; while (++row < height) { widget_move (view, top + row, left); tty_print_string (mcview_show_eof); } } }
static void edit_draw_this_line (WEdit * edit, off_t b, long row, long start_col, long end_col) { Widget *w = WIDGET (edit); struct line_s line[MAX_LINE_LEN]; struct line_s *p = line; off_t m1 = 0, m2 = 0, q; int col, start_col_real; int color; int abn_style; int book_mark = 0; char line_stat[LINE_STATE_WIDTH + 1] = "\0"; if (row > w->lines - 1 - EDIT_TEXT_VERTICAL_OFFSET - 2 * (edit->fullscreen ? 0 : 1)) return; if (book_mark_query_color (edit, edit->start_line + row, BOOK_MARK_COLOR)) book_mark = BOOK_MARK_COLOR; else if (book_mark_query_color (edit, edit->start_line + row, BOOK_MARK_FOUND_COLOR)) book_mark = BOOK_MARK_FOUND_COLOR; if (book_mark) abn_style = book_mark << 16; else abn_style = MOD_ABNORMAL; end_col -= EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width; if (!edit->fullscreen) { end_col--; if (w->x + w->cols <= WIDGET (w->owner)->cols) end_col--; } color = edit_get_syntax_color (edit, b - 1); q = edit_move_forward3 (edit, b, start_col - edit->start_col, 0); start_col_real = (col = (int) edit_move_forward3 (edit, b, 0, q)) + edit->start_col; if (option_line_state) { unsigned int cur_line; cur_line = edit->start_line + row; if (cur_line <= (unsigned int) edit->buffer.lines) { g_snprintf (line_stat, LINE_STATE_WIDTH + 1, "%7i ", cur_line + 1); } else { memset (line_stat, ' ', LINE_STATE_WIDTH); line_stat[LINE_STATE_WIDTH] = '\0'; } if (book_mark_query_color (edit, cur_line, BOOK_MARK_COLOR)) { g_snprintf (line_stat, 2, "*"); } } if (col + 16 > -edit->start_col) { eval_marks (edit, &m1, &m2); if (row <= edit->buffer.lines - edit->start_line) { off_t tws = 0; if (tty_use_colors () && visible_tws) { unsigned int c; tws = edit_buffer_get_eol (&edit->buffer, b); while (tws > b && ((c = edit_buffer_get_byte (&edit->buffer, tws - 1)) == ' ' || c == '\t')) tws--; } while (col <= end_col - edit->start_col) { int char_length = 1; unsigned int c; gboolean wide_width_char = FALSE; gboolean control_char = FALSE; p->ch = 0; p->style = 0; if (q == edit->buffer.curs1) p->style |= MOD_CURSOR; if (q >= m1 && q < m2) { if (edit->column_highlight) { long x; long c1, c2; x = (long) edit_move_forward3 (edit, b, 0, q); c1 = min (edit->column1, edit->column2); c2 = max (edit->column1, edit->column2); if (x >= c1 && x < c2) p->style |= MOD_MARKED; } else p->style |= MOD_MARKED; } if (q == edit->bracket) p->style |= MOD_BOLD; if (q >= edit->found_start && q < (off_t) (edit->found_start + edit->found_len)) p->style |= MOD_BOLD; #ifdef HAVE_CHARSET if (edit->utf8) c = edit_buffer_get_utf (&edit->buffer, q, &char_length); else #endif c = edit_buffer_get_byte (&edit->buffer, q); /* we don't use bg for mc - fg contains both */ if (book_mark) { p->style |= book_mark << 16; } else { color = edit_get_syntax_color (edit, q); p->style |= color << 16; } switch (c) { case '\n': col = end_col - edit->start_col + 1; /* quit */ break; case '\t': { int tab_over; int i; i = TAB_SIZE - ((int) col % TAB_SIZE); tab_over = (end_col - edit->start_col) - (col + i - 1); if (tab_over < 0) i += tab_over; col += i; if (tty_use_colors () && ((visible_tabs || (visible_tws && q >= tws)) && enable_show_tabs_tws)) { if (p->style & MOD_MARKED) c = p->style; else if (book_mark) c |= book_mark << 16; else c = p->style | MOD_WHITESPACE; if (i > 2) { p->ch = '<'; p->style = c; p++; while (--i > 1) { p->ch = '-'; p->style = c; p++; } p->ch = '>'; p->style = c; p++; } else if (i > 1) { p->ch = '<'; p->style = c; p++; p->ch = '>'; p->style = c; p++; } else { p->ch = '>'; p->style = c; p++; } } else if (tty_use_colors () && visible_tws && q >= tws && enable_show_tabs_tws) { p->ch = '.'; p->style |= MOD_WHITESPACE; c = p->style & ~MOD_CURSOR; p++; while (--i) { p->ch = ' '; p->style = c; p++; } } else { p->ch |= ' '; c = p->style & ~MOD_CURSOR; p++; while (--i) { p->ch = ' '; p->style = c; p++; } } } break; case ' ': if (tty_use_colors () && visible_tws && q >= tws && enable_show_tabs_tws) { p->ch = '.'; p->style |= MOD_WHITESPACE; p++; col++; break; } /* fallthrough */ default: #ifdef HAVE_CHARSET if (mc_global.utf8_display) { if (!edit->utf8) { c = convert_from_8bit_to_utf_c ((unsigned char) c, edit->converter); } else { if (g_unichar_iswide (c)) { wide_width_char = TRUE; col++; } } } else if (edit->utf8) c = convert_from_utf_to_current_c (c, edit->converter); else c = convert_to_display_c (c); #endif /* Caret notation for control characters */ if (c < 32) { p->ch = '^'; p->style = abn_style; p++; p->ch = c + 0x40; p->style = abn_style; p++; col += 2; control_char = TRUE; break; } if (c == 127) { p->ch = '^'; p->style = abn_style; p++; p->ch = '?'; p->style = abn_style; p++; col += 2; control_char = TRUE; break; } #ifdef HAVE_CHARSET if (edit->utf8) { if (g_unichar_isprint (c)) p->ch = c; else { p->ch = '.'; p->style = abn_style; } p++; } else #endif { if ((mc_global.utf8_display && g_unichar_isprint (c)) || (!mc_global.utf8_display && is_printable (c))) { p->ch = c; p++; } else { p->ch = '.'; p->style = abn_style; p++; } } col++; break; } /* case */ q++; if (char_length > 1) q += char_length - 1; if (col > (end_col - edit->start_col + 1)) { if (wide_width_char) { p--; break; } if (control_char) { p -= 2; break; } } } } } else { start_col_real = start_col = 0; } p->ch = 0; print_to_widget (edit, row, start_col, start_col_real, end_col, line, line_stat, book_mark); }
void mcview_display_hex (WView * view) { const screen_dimen top = view->data_area.top; const screen_dimen left = view->data_area.left; const screen_dimen height = view->data_area.height; const screen_dimen width = view->data_area.width; const int ngroups = view->bytes_per_line / 4; /* 8 characters are used for the file offset, and every hex group * takes 13 characters. Starting at width of 80 columns, the groups * are separated by an extra vertical line. Starting at width of 81, * there is an extra space before the text column. There is always a * mostly empty column on the right, to allow overflowing CJKs. */ const screen_dimen text_start = 8 + 13 * ngroups + ((width < 80) ? 0 : (width == 80) ? (ngroups - 1) : (ngroups - 1 + 1)); int row; off_t from; mark_t boldflag_byte = MARK_NORMAL; mark_t boldflag_char = MARK_NORMAL; struct hexedit_change_node *curr = view->change_list; #ifdef HAVE_CHARSET int cont_bytes = 0; /* number of continuation bytes remanining from current UTF-8 */ gboolean cjk_right = FALSE; /* whether the second byte of a CJK is to be processed */ #endif /* HAVE_CHARSET */ gboolean utf8_changed = FALSE; /* whether any of the bytes in the UTF-8 were changed */ char hex_buff[10]; /* A temporary buffer for sprintf and mvwaddstr */ mcview_display_clean (view); /* Find the first displayable changed byte */ /* In UTF-8 mode, go back by 1 or maybe 2 lines to handle continuation bytes properly. */ from = view->dpy_start; row = 0; #ifdef HAVE_CHARSET if (view->utf8) { if (from >= view->bytes_per_line) { row--; from -= view->bytes_per_line; } if (view->bytes_per_line == 4 && from >= view->bytes_per_line) { row--; from -= view->bytes_per_line; } } #endif /* HAVE_CHARSET */ while (curr && (curr->offset < from)) { curr = curr->next; } for (; mcview_get_byte (view, from, NULL) && row < (int) height; row++) { screen_dimen col = 0; size_t i; int bytes; /* Number of bytes already printed on the line */ /* Print the hex offset */ if (row >= 0) { g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from); widget_move (view, top + row, left); tty_setcolor (VIEW_BOLD_COLOR); for (i = 0; col < width && hex_buff[i] != '\0'; col++, i++) tty_print_char (hex_buff[i]); tty_setcolor (VIEW_NORMAL_COLOR); } for (bytes = 0; bytes < view->bytes_per_line; bytes++, from++) { int c; #ifdef HAVE_CHARSET int ch = 0; if (view->utf8) { struct hexedit_change_node *corr = curr; if (cont_bytes != 0) { /* UTF-8 continuation bytes, print a space (with proper attributes)... */ cont_bytes--; ch = ' '; if (cjk_right) { /* ... except when it'd wipe out the right half of a CJK, then print nothing */ cjk_right = FALSE; ch = -1; } } else { int j; gchar utf8buf[UTF8_CHAR_LEN + 1]; int res; int first_changed = -1; for (j = 0; j < UTF8_CHAR_LEN; j++) { if (mcview_get_byte (view, from + j, &res)) utf8buf[j] = res; else { utf8buf[j] = '\0'; break; } if (curr != NULL && from + j == curr->offset) { utf8buf[j] = curr->value; if (first_changed == -1) first_changed = j; } if (curr != NULL && from + j >= curr->offset) curr = curr->next; } utf8buf[UTF8_CHAR_LEN] = '\0'; /* Determine the state of the current multibyte char */ ch = g_utf8_get_char_validated (utf8buf, -1); if (ch == -1 || ch == -2) { ch = '.'; } else { gchar *next_ch; next_ch = g_utf8_next_char (utf8buf); cont_bytes = next_ch - utf8buf - 1; if (g_unichar_iswide (ch)) cjk_right = TRUE; } utf8_changed = (first_changed >= 0 && first_changed <= cont_bytes); curr = corr; } } #endif /* HAVE_CHARSET */ /* For negative rows, the only thing we care about is overflowing * UTF-8 continuation bytes which were handled above. */ if (row < 0) { if (curr != NULL && from == curr->offset) curr = curr->next; continue; } if (!mcview_get_byte (view, from, &c)) break; /* Save the cursor position for mcview_place_cursor() */ if (from == view->hex_cursor && !view->hexview_in_text) { view->cursor_row = row; view->cursor_col = col; } /* Determine the state of the current byte */ boldflag_byte = mcview_hex_calculate_boldflag (view, from, curr, FALSE); boldflag_char = mcview_hex_calculate_boldflag (view, from, curr, utf8_changed); /* Determine the value of the current byte */ if (curr != NULL && from == curr->offset) { c = curr->value; curr = curr->next; } /* Select the color for the hex number */ tty_setcolor (boldflag_byte == MARK_NORMAL ? VIEW_NORMAL_COLOR : boldflag_byte == MARK_SELECTED ? VIEW_BOLD_COLOR : boldflag_byte == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : /* boldflag_byte == MARK_CURSOR */ view->hexview_in_text ? VIEW_SELECTED_COLOR : VIEW_UNDERLINED_COLOR); /* Print the hex number */ widget_move (view, top + row, left + col); if (col < width) { tty_print_char (hex_char[c / 16]); col += 1; } if (col < width) { tty_print_char (hex_char[c % 16]); col += 1; } /* Print the separator */ tty_setcolor (VIEW_NORMAL_COLOR); if (bytes != view->bytes_per_line - 1) { if (col < width) { tty_print_char (' '); col += 1; } /* After every four bytes, print a group separator */ if (bytes % 4 == 3) { if (view->data_area.width >= 80 && col < width) { tty_print_one_vline (TRUE); col += 1; } if (col < width) { tty_print_char (' '); col += 1; } } } /* Select the color for the character; this differs from the * hex color when boldflag == MARK_CURSOR */ tty_setcolor (boldflag_char == MARK_NORMAL ? VIEW_NORMAL_COLOR : boldflag_char == MARK_SELECTED ? VIEW_BOLD_COLOR : boldflag_char == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : /* boldflag_char == MARK_CURSOR */ view->hexview_in_text ? VIEW_SELECTED_COLOR : MARKED_SELECTED_COLOR); #ifdef HAVE_CHARSET if (mc_global.utf8_display) { if (!view->utf8) { c = convert_from_8bit_to_utf_c ((unsigned char) c, view->converter); } if (!g_unichar_isprint (c)) c = '.'; } else if (view->utf8) ch = convert_from_utf_to_current_c (ch, view->converter); else #endif { #ifdef HAVE_CHARSET c = convert_to_display_c (c); #endif if (!is_printable (c)) c = '.'; } /* Print corresponding character on the text side */ if (text_start + bytes < width) { widget_move (view, top + row, left + text_start + bytes); #ifdef HAVE_CHARSET if (view->utf8) tty_print_anychar (ch); else #endif tty_print_char (c); } /* Save the cursor position for mcview_place_cursor() */ if (from == view->hex_cursor && view->hexview_in_text) { view->cursor_row = row; view->cursor_col = text_start + bytes; } } } /* Be polite to the other functions */ tty_setcolor (VIEW_NORMAL_COLOR); mcview_place_cursor (view); view->dpy_end = from; }