📄 view.c
字号:
return init_growing_view (view, 0, filename);
}
/* First, try to open a compressed file */
if (view->viewer_magic_flag && (is_gunzipable (view->file, &type)) != 0){
close_view_file (view);
if (vfs_file_is_local (filename)) {
char *tmp = name_quote (filename, 0);
cmd = copy_strings (decompress_command (type), " ", tmp, 0);
free (tmp);
}
else {
char *tmp;
if ((view->localcopy = mc_getlocalcopy (filename)) == 0)
return set_view_init_error (view, _(" Can not fetch local copy ") );
tmp = name_quote (view->localcopy, 0);
cmd = copy_strings (decompress_command (type), " ", tmp, 0);
free (tmp);
}
return init_growing_view (view, cmd, filename);
}
/* Otherwise, the file wasn't compressed */
#ifdef HAVE_MMAP
view->data = mc_mmap (0, view->s.st_size, PROT_READ, MAP_FILE | MAP_SHARED,
view->file, 0);
if ((caddr_t) view->data == (caddr_t) -1){
close_view_file (view);
/* set_view_init_error (view, 0);
return copy_strings (" Can't mmap file \n ",
unix_error_string (errno), " ", 0);*/
return init_growing_view (view, 0, filename);
}
view->first = 0;
view->bytes_read = view->s.st_size;
view->mmapping = 1;
return 0;
#else /* ! HAVE_MMAP */
/*
** For those OS that dont provide mmap call. Try to load all the file
** into memory (alex@bcs.zaporizhzhe.ua)
*/
view->data = (char*) xmalloc (view->s.st_size, "load_view_file");
if (view->data == NULL
|| mc_lseek(view->file,0,0) != 0
|| mc_read(view->file, view->data, view->s.st_size) != view->s.st_size
) {
if (view->data != NULL)
free(view->data);
close_view_file (view);
return init_growing_view (view, 0, filename);
}
view->first = 0;
view->bytes_read = view->s.st_size;
return 0;
#endif
}
/* Return zero on success, -1 on failure */
int
do_view_init (WView *view, char *_command, char *_file, int start_line)
{
char *error = 0;
int i;
if (view->view_active)
view_done (view);
/* Set up the state */
view->block_ptr = 0;
view->data = NULL;
view->growing_buffer = 0;
view->reading_pipe = 0;
view->mmapping = 0;
view->blocks = 0;
view->block_ptr = 0;
view->first = view->bytes_read = 0;
view->last_byte = 0;
view->filename = 0;
view->localcopy = 0;
view->command = 0;
view->last = view->first + ((LINES-2) * view->bytes_per_line);
/* Clear the markers */
view->marker = 0;
for (i = 0; i < 10; i++)
view->marks [i] = 0;
if (!view->have_frame){
view->start_col = 0;
}
if (_command && (view->viewer_magic_flag || _file[0] == '\0'))
error = init_growing_view (view, _command, _file);
else
error = load_view_file (view, _file);
if (error){
if (!view->have_frame){
message (1, MSG_ERROR, error);
free (error);
return -1;
}
}
view->view_active = 1;
view->filename = strdup (_file);
if (_command)
view->command = strdup (_command);
else
view->command = 0;
view->search_start = view->start_display = view->start_save = view->first;
view->found_len = 0;
view->start_col = 0;
view->last_search = 0; /* Start a new search */
/* Special case: The data points to the error message */
if (error){
view->data = error;
view->s.st_size = view->bytes_read = strlen (view->data);
}
view->last_byte = view->first + view->s.st_size;
if (start_line > 1 && !error){
int saved_wrap_mode = view->wrap_mode;
view->wrap_mode = 0;
get_byte (view, 0);
view_move_forward (view, start_line - 1);
view->wrap_mode = saved_wrap_mode;
}
view->edit_cursor = view->first;
view->file_dirty = 0;
view->nib_shift = 0;
view->view_side = view_side_left;
view->change_list = NULL;
return 0;
}
/* Both views */
/* Return zero on success, -1 on failure */
int
view_init (WView *view, char *_command, char *_file, int start_line)
{
int cols;
if (view->have_frame)
cols = view->widget.cols - 2;
else
cols = view->widget.cols;
view->bottom_first = -1;
view->bytes_per_line = 2 * (cols - 7) / 9;
view->bytes_per_line &= 0xfffc;
view->dirty = max_dirt_limit + 1; /* To force refresh */
if (!view->view_active || strcmp (_file, view->filename) || altered_magic_flag)
return do_view_init (view, _command, _file, start_line);
else
return 0;
}
/* }}} */
/* {{{ Screen update functions */
#ifndef HAVE_X
void
view_percent (WView *view, int p, int w)
{
int percent;
percent = (view->s.st_size == 0 || view->last_byte == view->last) ? 100 :
(p > (INT_MAX/100) ?
p / (view->s.st_size / 100) :
p * 100 / view->s.st_size);
#if 0
percent = view->s.st_size == 0 ? 100 :
(view->last_byte == view->last ? 100 :
(p)*100 / view->s.st_size);
#endif
widget_move (view, view->have_frame, w - 5);
printw ("%3d%% ", percent);
}
void
view_status (WView *view)
{
int w = view->widget.cols - (view->have_frame * 2);
int i;
attrset (SELECTED_COLOR);
widget_move (view, view->have_frame, view->have_frame);
hline (' ', w);
if (w > 6){
i = w > 24 ? 18 : w - 6;
printw (_("File: %s"), name_trunc (view->filename ? view->filename:
view->command ? view->command:"", i));
if (w > 30){
widget_move (view, view->have_frame, 24);
if (view->hex_mode)
printw (_("Offset 0x%08x"), view->edit_cursor);
else
printw (_("Col %d"), -view->start_col);
}
if (w > 60){
widget_move (view, view->have_frame, 42);
printw (_("%s bytes"), size_trunc (view->s.st_size));
}
if (w > 70){
printw (" ");
if (view->growing_buffer)
addstr (_(" [grow]"));
}
if (w - i > 4)
if (view->hex_mode)
view_percent (view, view->edit_cursor - view->first, w);
else
view_percent (view, view->start_display - view->first, w);
}
attrset (SELECTED_COLOR);
}
#define view_set_color(view,font) attrset (font)
static inline void
view_display_clean (WView *view, int height, int width)
{
/* FIXME: Should I use widget_erase only and repaint the box? */
if (view->have_frame){
int i;
draw_double_box (view->widget.parent, view->widget.y, view->widget.x,
view->widget.lines, view->widget.cols);
for (i = 1; i < height; i++){
widget_move (view, i, 1);
printw ("%*s", width-1, "");
}
} else
widget_erase ((Widget *) view);
}
#define view_add_character(view,c) addch (c)
#define view_add_string(view,s) addstr (s)
#define view_gotoyx(v,r,c) widget_move (v,r,c)
#endif
#ifndef HAVE_TK
/* Both the text mode and gnome editions use this */
#define BOLD_COLOR MARKED_COLOR
#define UNDERLINE_COLOR VIEW_UNDERLINED_COLOR
#define MARK_COLOR SELECTED_COLOR
#define DEF_COLOR NORMAL_COLOR
#endif
#ifndef PORT_HAS_VIEW_FREEZE
# define view_freeze(view)
# define view_thaw(view)
#endif
#ifdef HAVE_GNOME
# define PICK_COLOR(a,b) BOLD_COLOR : DEF_COLOR
#else
# define PICK_COLOR(a,b) a : b
#endif
/* Shows the file pointed to by *start_display on view_win */
static long
display (WView *view)
{
#ifdef HAVE_X
# define frame_shift 0
# define STATUS_LINES 0
#else
const int frame_shift = view->have_frame;
# define STATUS_LINES 1
#endif
int col = 0 + frame_shift;
int row = STATUS_LINES + frame_shift;
int height, width;
long from;
int c;
int boldflag = 0;
struct hexedit_change_node *curr = view->change_list;
height = view->widget.lines - frame_shift;
width = view->widget.cols - frame_shift;
from = view->start_display;
view_set_color (view, DEF_COLOR);
view_freeze (view);
view_display_clean (view, height, width);
/* Optionally, display a ruler */
if ((!view->hex_mode) && (ruler)){
char r_buff[4];
int cl;
view_set_color (view, BOLD_COLOR);
for (c = frame_shift; c < width; c++) {
cl = c-view->start_col;
if (ruler == 1)
view_gotoyx (view, row, c);
else
view_gotoyx (view, row+height-2, c);
r_buff[0] = '-';
if ((cl % 10) == 0)
r_buff[0] = '|';
else
if ((cl % 5) == 0)
r_buff[0] = '*';
view_add_character (view, r_buff[0]);
if ((cl != 0) && (cl % 10) == 0){
sprintf(r_buff, "%03d", cl);
if (ruler == 1)
widget_move (view, row + 1, c - 1);
else
widget_move (view, row + height - 3, c - 1);
view_add_string (view, r_buff);
}
}
view_set_color (view, DEF_COLOR);
if (ruler == 1)
row += 2;
else
height -= 2;
}
/* Find the first displayable changed byte */
while (curr) {
if (curr->offset < from)
curr = curr->next;
else
break;
}
if (view->hex_mode){
char hex_buff[10]; /* A temporary buffer for sprintf and mvwaddstr */
int bytes; /* Number of bytes already printed on the line */
/* Start of text column */
int text_start = width - view->bytes_per_line - 1 + frame_shift;
for (;row < height && from < view->last_byte; row++){
/* Print the hex offset */
sprintf (hex_buff, "%05X", (int) (from - view->first));
widget_move (view, row, frame_shift);
view_add_string (view, hex_buff);
/* Hex dump starts from column seven */
col = 7;
/* Each hex number is two digits */
hex_buff[2] = 0;
for (bytes = 0; bytes < view->bytes_per_line
&& from < view->last_byte; bytes++, from++){
/* Display and mark changed bytes */
if (curr && from == curr->offset) {
c = curr->value;
curr = curr->next;
boldflag = 3;
view_set_color (view, 7);
} else
c = (unsigned char) get_byte (view, from);
if (view->found_len && from >= view->search_start
&& from < view->search_start + view->found_len){
boldflag = 1;
view_set_color (view, BOLD_COLOR);
}
/* Display the navigation cursor */
if (from == view->edit_cursor) {
if (view->view_side == view_side_left){
view->cursor_row = row;
view->cursor_col = col;
}
boldflag = 2;
view_set_color (view, view->view_side == view_side_left ? PICK_COLOR (15, 31));
}
/* Print a hex number (sprintf is too slow) */
hex_buff [0] = hex_char [(c >> 4)];
hex_buff [1] = hex_char [c & 15];
view_gotoyx (view, row, col);
view_add_string (view, hex_buff);
col += 3;
/* Turn off the cursor or changed byte highlighting here */
if (boldflag > 1)
view_set_color (view, DEF_COLOR);
if ((bytes & 3) == 3 && bytes + 1 < view->bytes_per_line){
/* Turn off the search highlighting */
if (boldflag == 1 &&
from == view->search_start + view->found_len - 1)
view_set_color (view, DEF_COLOR);
/* Hex numbers are printed in the groups of four */
/* Groups are separated by a vline */
view_add_character (view, ' ');
one_vline ();
view_gotoyx (view, row, col + 1);
col += 2;
if (boldflag && from==view->search_start+view->found_len-1)
view_set_color (view, BOLD_COLOR);
}
if (boldflag && from < view->search_start + view->found_len - 1
&& bytes != view->bytes_per_line - 1)
view_add_character (view, ' ');
/* Print the corresponding ascii character */
view_gotoyx (view, row, text_start + bytes);
if (!is_printable (c))
c = '.';
switch (boldflag) {
default:
break;
case 1:
view_set_color (view, BOLD_COLOR);
goto setcursor;
case 2:
view_set_color (view, view->view_side == view_side_left ? PICK_COLOR (31, 15));
goto setcursor;
case 3:
view_set_color (view, 7);
setcursor:
if (view->view_side == view_side_right){
view->cursor_col = text_start + bytes;
view->cursor_row = row;
}
}
view_add_character (view, c);
if (boldflag){
boldflag = 0;
view_set_color (view, DEF_COLOR);
}
}
}
} else {
if (view->growing_buffer && from == view->last_byte)
get_byte (view, from);
for (; row < height && from < view->last_byte; from++){
c = get_byte (view, from);
if ((c == '\n') || (col == width && view->wrap_mode)){
col = frame_shift;
row++;
if (c == '\n' || row >= height)
continue;
}
if (c == '\r')
continue;
if (c == '\t'){
col = ((col - frame_shift)/8)*8 + 8 + frame_shift;
continue;
}
if (view->viewer_nroff_flag && c == '\b'){
if (from + 1 < view->last_byte
&& is_printable (get_byte (view, from + 1)) &&
from > view->first
&& is_printable (get_byte (view, from - 1)))
{
if (col <= frame_shift){
/* So it has to be wrap_mode - do not need to check for it */
if (row == 1 + frame_shift){
from++;
continue; /* There had to be a bold character on the rightmost position
of the previous undisplayed line */
}
row--;
col = width;
}
col--;
boldflag = 1;
if (get_byte (view, from - 1) == '_' && get_byte (view, from + 1) != '_')
view_set_color (view, UNDERLINE_COLOR);
else
view_set_color (view, BOLD_COLOR);
continue;
}
}
if (view->found_len && from >= view->search_start
&& from < view->search_start + view->found_len){
boldflag = 1;
view_set_color (view, MARK_COLOR);
}
if (col >= frame_shift-view->start_col
&& col < width-view->start_col)
{
view_gotoyx (view, row, col+view->start_col);
if (!is_printable (c))
c = '.';
view_add_character (view, c);
}
col++;
if (boldflag){
boldflag = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -