void mcview_moveto_eol (WView * view) { off_t bol; if (view->mode_flags.hex) { off_t filesize; bol = mcview_offset_rounddown (view->hex_cursor, view->bytes_per_line); if (mcview_get_byte_indexed (view, bol, view->bytes_per_line - 1, NULL) == TRUE) { view->hex_cursor = bol + view->bytes_per_line - 1; } else { filesize = mcview_get_filesize (view); view->hex_cursor = mcview_offset_doz (filesize, 1); } } else { mcview_ascii_moveto_eol (view); } mcview_movement_fixups (view, FALSE); }
void mcview_moveto_eol (mcview_t * view) { off_t bol; if (view->hex_mode) { off_t filesize; bol = mcview_offset_rounddown (view->hex_cursor, view->bytes_per_line); if (mcview_get_byte_indexed (view, bol, view->bytes_per_line - 1, NULL) == TRUE) { view->hex_cursor = bol + view->bytes_per_line - 1; } else { filesize = mcview_get_filesize (view); view->hex_cursor = mcview_offset_doz (filesize, 1); } } else { off_t eol; bol = mcview_bol (view, view->dpy_start, 0); eol = mcview_eol (view, view->dpy_start, mcview_get_filesize (view)); if (!view->utf8) { if (eol > bol) view->dpy_text_column = eol - bol; } else { char *str = NULL; switch (view->datasource) { case DS_STDIO_PIPE: case DS_VFS_PIPE: str = mcview_get_ptr_growing_buffer (view, bol); break; case DS_FILE: str = mcview_get_ptr_file (view, bol); break; case DS_STRING: str = mcview_get_ptr_string (view, bol); break; case DS_NONE: break; } if (str != NULL && eol > bol) view->dpy_text_column = g_utf8_strlen (str, eol - bol); else view->dpy_text_column = eol - bol; } view->dpy_text_column = max (0, view->dpy_text_column - view->data_area.width); } mcview_movement_fixups (view, FALSE); }
void mcview_ccache_lookup (mcview_t * view, coord_cache_entry_t * coord, enum ccache_type lookup_what) { size_t i; coord_cache_t *cache; coord_cache_entry_t current, next, entry; enum ccache_type sorter; off_t limit; cmp_func_t cmp_func; enum { NROFF_START, NROFF_BACKSPACE, NROFF_CONTINUATION } nroff_state; if (view->coord_cache == NULL) view->coord_cache = coord_cache_new (); cache = view->coord_cache; if (cache->size == 0) { current.cc_offset = 0; current.cc_line = 0; current.cc_column = 0; current.cc_nroff_column = 0; mcview_ccache_add_entry (cache, 0, ¤t); } sorter = (lookup_what == CCACHE_OFFSET) ? CCACHE_LINECOL : CCACHE_OFFSET; if (sorter == CCACHE_OFFSET) cmp_func = mcview_coord_cache_entry_less_offset; else if (view->text_nroff_mode) cmp_func = mcview_coord_cache_entry_less_nroff; else cmp_func = mcview_coord_cache_entry_less_plain; tty_enable_interrupt_key (); retry: /* find the two neighbor entries in the cache */ i = mcview_ccache_find (view, coord, cmp_func); /* now i points to the lower neighbor in the cache */ current = *cache->cache[i]; if (i + 1 < view->coord_cache->size) limit = cache->cache[i + 1]->cc_offset; else limit = current.cc_offset + VIEW_COORD_CACHE_GRANUL; entry = current; nroff_state = NROFF_START; for (; current.cc_offset < limit; current = next) { int c, nextc; if (!mcview_get_byte (view, current.cc_offset, &c)) break; if (!cmp_func (¤t, coord)) { if (lookup_what == CCACHE_OFFSET && view->text_nroff_mode && nroff_state != NROFF_START) { /* don't break here */ } else { break; } } /* Provide useful default values for ''next'' */ next.cc_offset = current.cc_offset + 1; next.cc_line = current.cc_line; next.cc_column = current.cc_column + 1; next.cc_nroff_column = current.cc_nroff_column + 1; /* and override some of them as necessary. */ if (c == '\r') { mcview_get_byte_indexed (view, current.cc_offset, 1, &nextc); /* Ignore '\r' if it is followed by '\r' or '\n'. If it is * followed by anything else, it is a Mac line ending and * produces a line break. */ if (nextc == '\r' || nextc == '\n') { next.cc_column = current.cc_column; next.cc_nroff_column = current.cc_nroff_column; } else { next.cc_line = current.cc_line + 1; next.cc_column = 0; next.cc_nroff_column = 0; } } else if (nroff_state == NROFF_BACKSPACE) { next.cc_nroff_column = current.cc_nroff_column - 1; } else if (c == '\t') { next.cc_column = mcview_offset_rounddown (current.cc_column, 8) + 8; next.cc_nroff_column = mcview_offset_rounddown (current.cc_nroff_column, 8) + 8; } else if (c == '\n') { next.cc_line = current.cc_line + 1; next.cc_column = 0; next.cc_nroff_column = 0; } else { /* Use all default values from above */ } switch (nroff_state) { case NROFF_START: case NROFF_CONTINUATION: nroff_state = mcview_is_nroff_sequence (view, current.cc_offset) ? NROFF_BACKSPACE : NROFF_START; break; case NROFF_BACKSPACE: nroff_state = NROFF_CONTINUATION; break; } /* Cache entries must guarantee that for each i < j, * line[i] <= line[j] and column[i] < column[j]. In the case of * nroff sequences and '\r' characters, this is not guaranteed, * so we cannot save them. */ if (nroff_state == NROFF_START && c != '\r') entry = next; } if (i + 1 == cache->size && entry.cc_offset != cache->cache[i]->cc_offset) { mcview_ccache_add_entry (cache, cache->size, &entry); if (!tty_got_interrupt ()) goto retry; } tty_disable_interrupt_key (); if (lookup_what == CCACHE_OFFSET) { coord->cc_offset = current.cc_offset; } else { coord->cc_line = current.cc_line; coord->cc_column = current.cc_column; coord->cc_nroff_column = current.cc_nroff_column; } }
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; }