⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 view.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
		view_set_color (view, DEF_COLOR);
	    }

	    /* Very last thing */
	    if (view->growing_buffer && from+1 == view->last_byte)
		 get_byte (view, from+1);
        }
#ifdef HAVE_TK
	view_gotoyx (view, view->current_line+1, 0);
#endif
    }
    view->last = from;
    view_thaw (view);
    return from;
}

void
view_place_cursor (WView *view)
{
    int shift;

    if (view->view_side == view_side_left)
	shift = view->nib_shift;
    else
	shift = 0;

    widget_move (&view->widget, view->cursor_row, view->cursor_col + shift);
}

void
view_update (WView *view)
{
    static int dirt_limit = 1;

    if (view->dirty > dirt_limit){
	/* Too many updates skipped -> force a update */
	display (view);
	view_status (view);
	view->dirty = 0;
	/* Raise the update skipping limit */
	dirt_limit++;
	if (dirt_limit > max_dirt_limit)
	    dirt_limit = max_dirt_limit;
    }
    if (view->dirty){
	if (is_idle ()){
	    /* We have time to update the screen properly */
	    display (view);
	    view_status (view);
	    view->dirty = 0;
	    if (dirt_limit > 1)
		dirt_limit--;
	} else {
	    /* We are busy -> skipping full update,
	       only the status line is updated */
	    view_status (view);
	}
	/* Here we had a refresh, if fast scrolling does not work
	   restore the refresh, although this should not happen */
    }
}

static inline void
my_define (Dlg_head *h, int idx, char *text,
			 void (*fn)(WView *), WView *view)
{
    define_label_data (h, (Widget *) view, idx, text, (buttonbarfn) fn, view);
}

/* }}} */
/* {{{ Movement functions */
/* If the last parameter is nonzero, it means we want get the count of lines
   from current up to the the upto position inclusive */
static long
move_forward2 (WView *view, long current, int lines, long upto)
{
    long p, q;
    int  line;
    int  col = 0;

    if (view->hex_mode){
        p = current + lines * view->bytes_per_line;
        p = (p >= view->last_byte) ? current : p;
        if (lines == 1) {
            q = view->edit_cursor + view->bytes_per_line;
            line = q / view->bytes_per_line;
            col = (view->last_byte-1) / view->bytes_per_line;
            view->edit_cursor = (line > col) ? view->edit_cursor : q;
            view->edit_cursor = (view->edit_cursor < view->last_byte) ?
                view->edit_cursor : view->last_byte-1;
            q = current + ((LINES-2) * view->bytes_per_line);
            p = (view->edit_cursor < q) ? current : p;
        } else {
            view->edit_cursor = (view->edit_cursor < p) ?
                p : view->edit_cursor;
        }
        return p;
    } else {
    	if (upto){
    	    lines = -1;
    	    q = upto;
    	} else
    	    q = view->last_byte;
        if (get_byte (view, q) != '\n')
	    q++;
        for (line = col = 0, p = current; p < q; p++){
	    int c;

	    if (lines != -1 && line >= lines)
	        return p;

	    c = get_byte (view, p);

	    if (view->wrap_mode){
	    	if (c == '\r')
	    	    continue; /* This characters is never displayed */
	    	else if (c == '\t')
	    	    col = ((col - view->have_frame)/8)*8 +8+ view->have_frame;
		else
		    col++;
	    	if (view->viewer_nroff_flag && c == '\b'){
	    	    if (p + 1 < view->last_byte
			&& is_printable (get_byte (view, p + 1))
	    	        && p > view->first
			&& is_printable (get_byte (view, p - 1)))
		        col -= 2;
	        } else if (col == vwidth){
		    /* FIXME: the c in is_printable was a p, that is a bug,
		       I suspect I got that fix from Jakub, same applies
		       for d. */
		    int d = get_byte (view, p+2);

		    if (p + 2 >= view->last_byte || !is_printable (c) ||
		        !view->viewer_nroff_flag || get_byte (view, p + 1) != '\b' ||
		        !is_printable (d)){
		        col = 0;

		        if (c == '\n' || get_byte (view, p+1) != '\n')
		            line++;
		    }
		} else if (c == '\n'){
	            line++;
		    col = 0;
	        }
	    } else if (c == '\n')
	        line++;
        }
        if (upto)
            return line;
    }
    return current;
}

/* returns the new current pointer */
/* Cause even the forward routine became very complex, we in the wrap_mode
   just find the nearest '\n', use move_forward2(p, 0, q) to get the count
   of lines up to there and then use move_forward2(p, something, 0), which we
   return */
static long
move_backward2 (WView *view, long current, int lines)
{
    long p, q, pm;
    int line;

    if (!view->hex_mode && current == view->first)
        return current;

    if (view->hex_mode){
	p = current - lines * view->bytes_per_line;
        p = (p < view->first) ? view->first : p;
        if (lines == 1) {
            q = view->edit_cursor - view->bytes_per_line;
            view->edit_cursor = (q < view->first) ? view->edit_cursor : q;
            p = (view->edit_cursor >= current) ? current : p;
        } else {
            q = p + ((LINES-2) * view->bytes_per_line);
            view->edit_cursor = (view->edit_cursor >= q) ?
                p : view->edit_cursor;
        }
        return p;
    } else {
    	if (current == view->last_byte
	    && get_byte (view, current - 1) != '\n')
	    /* There is one virtual '\n' at the end,
	       so that the last line is shown */
  	    line = 1;
  	else
  	    line = 0;
        for (q = p = current - 1; p >= view->first; p--)
	    if (get_byte (view, p) == '\n' || p == view->first) {
	        pm = p > view->first ? p + 1 : view->first;
	    	if (!view->wrap_mode){
	            if (line == lines)
	            	return pm;
	            line++;
	        } else {
	            line += move_forward2 (view, pm, 0, q);
	            if (line >= lines){
	            	if (line == lines)
	            	    return pm;
	            	else
	            	    return move_forward2 (view, pm, line - lines, 0);
	            }
	            q = p + 1;
	        }
            }
    }
    return p > view->first ? p : view->first;
}

void
view_move_backward (WView *view, int i)
{
    view->search_start = view->start_display =
	move_backward2 (view, view->start_display, i);
    view->found_len = 0;
    view->last = view->first + ((LINES-2) * view->bytes_per_line);
    view->dirty++;
}

static long
get_bottom_first (WView *view, int do_not_cache, int really)
{
    int bottom_first;

    if (!have_fast_cpu && !really)
	return INT_MAX;

    if (!do_not_cache && view->bottom_first != -1)
    	return view->bottom_first;

    /* Force loading */
    if (view->growing_buffer){
	int old_last_byte;

	old_last_byte = -1;
	while (old_last_byte != view->last_byte){
	    old_last_byte = view->last_byte;
	    get_byte (view, view->last_byte+VIEW_PAGE_SIZE);
	}
    }

    bottom_first = move_backward2 (view, view->last_byte, vheight - 1);

    if (view->hex_mode)
    	bottom_first = (bottom_first + view->bytes_per_line - 1)
	    / view->bytes_per_line * view->bytes_per_line;
    view->bottom_first = bottom_first;

    return view->bottom_first;
}

void
view_move_forward (WView *view, int i)
{
    view->start_display = move_forward2 (view, view->start_display, i, 0);
    if (!view->reading_pipe && view->start_display > get_bottom_first (view, 0, 0))
    	view->start_display = view->bottom_first;
    view->search_start = view->start_display;
    view->found_len = 0;
    view->last = view->first + ((LINES-2) * view->bytes_per_line);
    view->dirty++;
}


static void
move_to_top (WView *view)
{
    view->search_start = view->start_display = view->first;
    view->found_len = 0;
    view->last = view->first + ((LINES-2) * view->bytes_per_line);
    view->nib_shift = 0;
    view->edit_cursor = view->start_display;
    view->dirty++;
}

static void
move_to_bottom (WView *view)
{
    view->search_start = view->start_display = get_bottom_first (view, 0, 1);
    view->found_len = 0;
    view->last = view->first + ((LINES-2) * view->bytes_per_line);
    view->edit_cursor = (view->edit_cursor < view->start_display) ?
        view->start_display : view->edit_cursor;
    view->dirty++;
}

/* Scroll left/right the view panel functions */
static void
move_right (WView *view)
{
    if (view->wrap_mode && !view->hex_mode)
        return;
    if (view->hex_mode) {
        view->last = view->first + ((LINES-2) * view->bytes_per_line);

        if (view->hex_mode && view->view_side == view_side_left) {
            view->nib_shift = 1 - view->nib_shift;
            if (view->nib_shift == 1)
                return;
        }
        view->edit_cursor = (++view->edit_cursor <  view->last_byte) ?
            view->edit_cursor : view->last_byte - 1;
        if (view->edit_cursor >= view->last) {
           view->edit_cursor -= view->bytes_per_line;
           view_move_forward(view, 1);
        }
    } else
    if (--view->start_col > 0)
	view->start_col = 0;
    view->dirty++;
}

static void
move_left (WView *view)
{
    if (view->wrap_mode && !view->hex_mode)
        return;
    if (view->hex_mode) {
        if (view->hex_mode && view->view_side == view_side_left) {
            view->nib_shift = 1 - view->nib_shift;
            if (view->nib_shift == 0)
                return;
        }
        view->edit_cursor = (--view->edit_cursor < view->first) ?
            view->first : view->edit_cursor;
        if (view->edit_cursor < view->start_display) {
           view->edit_cursor += view->bytes_per_line;
           view_move_backward(view, 1);
        }
    } else
    if (++view->start_col > 0)
	view->start_col = 0;
    view->dirty++;
}

/* }}} */
/* {{{ Search routines */

/* Case insensitive search of text in data */
static int
icase_search_p (WView *view, char *text, char *data, int nothing)
{
    int p = 0, lng;
    char *q;

    p = (q = _icase_search (text, data, &lng)) != 0;
    if (p) {
	view->found_len = lng;
	view->search_start = q - data - view->found_len;
    }
    return p;
}

static char *
grow_string_buffer (char *text, int *size)
{
    char *new;
    int  old_size = *size;

    /* The grow steps */
    *size += 160;
    new = xmalloc (*size, "grow_string_buffer");
    if (text){
	strncpy (new, text, old_size);
	free (text);
    } else {
        *new = 0;
    }
    return new;
}

static char *
get_line_at (WView *view, long *p)
{
    char *buffer = 0;
    int  buffer_size, usable_size;
    int  ch;
    int  direction;
    long pos = *p;
    long i;

    direction = view->direction;
    buffer_size = usable_size = 0;

    i = ch = 0;
    for (;pos >= 0 && (ch = get_byte (view, pos))!= -1; pos += direction, i++){

	/* skip over all the possible zeros in the file */
	if (ch == 0 && i == 0){
	    while (pos >= 0 && ((ch = get_byte (view, pos)) != -1) && ch == 0)
		pos+= direction;
	    if (ch == -1)
		break;
	}
	if (i == usable_size){
	    buffer = grow_string_buffer (buffer, &buffer_size);
	    usable_size = buffer_size - 2;
	    buffer [0] = ' '; /* This makes possible strcpy of buffer */
	}
	buffer [i+1] = ch;
	if (ch == '\n' || !ch || ch == -1){
	    pos += direction; i++;
	    break;
	}
    }
    if (buffer){
	i--;
	buffer [0] = ' ';
	buffer [i+1] = 0;

	/* If we are searching backwards, reverse the string */
	if (view->direction < 0)
	    reverse_string (buffer);
    }

    *p = pos;
    return buffer;
}

/** Search status optmizations **/

/* The number of bytes between percent increments */
int  update_steps;

/* Last point where we updated the status */
long update_activate;

static void
search_update_steps (WView *view)
{
    if (view->s.st_size)
	update_steps = 40000;
    else
	update_steps = view->last_byte / 100;

    /* Do not update the percent display but every 20 ks */
    if (update_steps < 20000)
	update_steps = 20000;
}

static void
search (WView *view, char *text, int (*search)(WView *, char *, char *, int))
{
    int w = view->widget.cols - (view->have_frame * 2);
    char *s = NULL;		/*  The line we read from the view buffer */
    long p, beginning;
    int  ch;
    int isatbeg; /* Nonzero means we start search at beginning of some line */
    int found_len, search_start;
    Dlg_head *d = 0;
    int search_status;

    /* Used to keep track of where the line starts, when looking forward */
    /* is the index before transfering the line; the reverse case uses   */
    /* the position returned after the line has been read */
    long forward_line_start;
    long reverse_line_start;
    long t;
    /* Clear interrupt status */
    got_interrupt ();

    if (verbose){
	d = message (D_INSERT, _(" Search "), _("Searching %s"), text);
	mc_refresh ();
    }
    ch = 0;
    if (view->direction == 1){
	p = view->found_len ? view->search_start + 1 : view->search_start;
    } else {
	p = (view->found_len ? view->search_start : view->last) - 1;
    }
    beginning = p;

    isatbeg = view->found_len == 0;
    found_len = view->found_len;
    search_start = view->search_start;

    /* Compute the percent steps */
    search_update_steps (view);
    update_activate = 0;

    for (; ; isatbeg = 1, free (s)){
#ifdef PORT_HAS_FLUSH_EVENTS
	static int count;

	if ((count++ % 32) == 0)
	    x_flush_events ();
	if (!d->running)
	    break;
#endif
	if (p >= update_activate){
	    update_activate += update_steps;
	    if (verbose){
		view_percent (view, p, w);
		mc_refresh ();
	    }
	    if (got_interrupt ())
		break;
	}
	forward_line_start = p;
	disable_interrupt_key ();
	s = get_line_at (view, &p);
	reverse_line_start = p;
	enable_interrupt_key ();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -