📄 view.c
字号:
if (!s)
break;
search_status = (*search) (view, text, s + 1, match_normal);
if (search_status < 0)
break;
if (search_status == 0)
continue;
/* We found the string */
if (!isatbeg && !view->search_start){
/* We do not want to match a
* ^ regexp when not at the real
* beginning of some line
*/
view->found_len = found_len;
view->search_start = search_start;
if ((*search) (view, text, s, match_normal) <= 0)
continue;
(*search) (view, text, s + 1, match_normal);
}
/* Record the position used to continue the search */
if (view->direction == 1)
t = forward_line_start;
else
t = reverse_line_start ? reverse_line_start + 3 : 0;
view->search_start += t;
if (t != beginning){
if (t > get_bottom_first (view, 0, 0))
view->start_display = view->bottom_first;
else
view->start_display = t;
}
free (s);
break;
}
disable_interrupt_key ();
if (verbose){
dlg_run_done (d);
destroy_dlg (d);
}
if (!s){
message (0, _(" Search "), _(" Search string not found "));
view->found_len = 0;
}
}
/* Search buffer (it's size is len) in the complete buffer */
/* returns the position where the block was found or -1 if not found */
static long
block_search (WView *view, char *buffer, int len)
{
int w = view->widget.cols - (view->have_frame * 2);
char *d = buffer, b;
long e;
/* clear interrupt status */
got_interrupt ();
enable_interrupt_key ();
e = view->found_len ? view->search_start + 1 : view->search_start;
search_update_steps (view);
update_activate = 0;
for (; e < view->last_byte; e++){
if (e >= update_activate){
update_activate += update_steps;
if (verbose){
view_percent (view, e, w);
mc_refresh ();
}
if (got_interrupt ())
break;
}
b = get_byte (view, e);
if (*d == b){
d++;
} else {
e -= d - buffer;
d = buffer;
}
if (d - buffer == len){
disable_interrupt_key ();
return e - len;
}
}
disable_interrupt_key ();
return -1;
}
/* States of our funny recognizer */
enum {
normal,
inside_quotes,
zero,
hex1,
hex2,
oct1
};
/* This routine doesn't report all the user mistakes, it just ignores them */
static void
hex_search (WView *view, char *text)
{
char buffer [120]; /* Where we hold the information */
int i, block_len;
int v = 0;
long pos; /* Where did we found the string */
char *p; /* Temporary */
int state = normal; /* Initial state of the micro-scanner */
/* First convert the string to a stream of bytes */
for (i = block_len = 0; text [i] && block_len < sizeof (buffer); i++){
switch (state){
case inside_quotes:
if (text [i] == '"')
state = normal;
else
buffer [block_len++] = text [i];
break;
case normal:
if (text [i] == '"'){
state = inside_quotes;
break;
}
if (text [i] == '0'){
state = zero;
break;
}
if (text [i] == 'x'){
state = hex1;
break;
}
break;
case zero:
if (text [i] == 'x')
state = hex1;
break;
case hex1:
v = 0;
text [i] = toupper (text [i]);
if ((p = strchr (hex_char, text [i])) != 0){
v = (p - hex_char) << 4;
state = hex2;
}
break;
case hex2:
text [i] = toupper (text [i]);
if ((p = strchr (hex_char, text [i])) != 0){
v |= (p - hex_char);
state = normal;
}
buffer [block_len++] = v;
break;
}
}
/* Then start the search */
pos = block_search (view, buffer, block_len);
if (pos == -1){
message (0, _(" Search "), _(" Search string not found "));
view->found_len = 0;
return;
}
view->search_start = pos + 1;
view->found_len = block_len;
/* Set the edit cursor to the search position, left nibble */
view->edit_cursor = view->search_start;
view->nib_shift = 0;
/* Adjust the file offset */
view->start_display = (pos & (~(view->bytes_per_line-1)));
if (view->start_display > get_bottom_first (view, 0, 0))
view->start_display = view->bottom_first;
}
static int regexp_view_search (WView *view, char *pattern, char *string, int match_type)
{
static regex_t r;
static char *old_pattern = NULL;
static int old_type;
regmatch_t pmatch[1];
int i, flags = REG_ICASE;
if (!old_pattern || strcmp (old_pattern, pattern) || old_type != match_type){
if (old_pattern){
regfree (&r);
free (old_pattern);
old_pattern = 0;
}
for (i = 0; pattern[i] != 0; i++){
if (isupper ((unsigned char) pattern[i])){
flags = 0;
break;
}
}
flags |= REG_EXTENDED;
if (regcomp (&r, pattern, flags)){
message (1, MSG_ERROR, _(" Invalid regular expression "));
return -1;
}
old_pattern = strdup (pattern);
old_type = match_type;
}
if (regexec (&r, string, 1, pmatch, 0) != 0)
return 0;
view->found_len = pmatch[0].rm_eo - pmatch[0].rm_so;
view->search_start = pmatch[0].rm_so;
return 1;
}
static void do_regexp_search (void *xview, char *regexp)
{
WView *view = (WView *) xview;
view->search_exp = regexp;
search (view, regexp, regexp_view_search);
/* Had a refresh here */
view->dirty++;
view_update (view);
}
static void do_normal_search (void *xview, char *text)
{
WView *view = (WView *) xview;
view->search_exp = text;
if (view->hex_mode)
hex_search (view, text);
else
search (view, text, icase_search_p);
/* Had a refresh here */
view->dirty++;
view_update (view);
}
/* }}} */
/* {{{ Mouse and keyboard handling */
/* Real view only */
static void help_cmd (void)
{
char *hlpfile = concat_dir_and_file (mc_home, "mc.hlp");
interactive_display (hlpfile, "[Internal File Viewer]");
free (hlpfile);
/*
view_refresh (0);
*/
}
/* Both views */
void toggle_wrap_mode (WView *view)
{
if (view->hex_mode) {
if (view->growing_buffer != 0) {
return;
}
get_bottom_first (view, 1, 1);
if (view->hexedit_mode) {
view->view_side = 1 - view->view_side;
} else {
view->hexedit_mode = 1 - view->hexedit_mode;
}
view_labels (view);
view->dirty++;
view_update (view);
return;
}
view->wrap_mode = 1 - view->wrap_mode;
get_bottom_first (view, 1, 1);
if (view->wrap_mode)
view->start_col = 0;
else {
if (have_fast_cpu){
if (view->bottom_first < view->start_display)
view->search_start = view->start_display = view->bottom_first;
view->found_len = 0;
}
}
view_labels (view);
view->dirty++;
view_update (view);
}
/* Both views */
void
toggle_hex_mode (WView *view)
{
view->hex_mode = 1 - view->hex_mode;
if (view->hex_mode){
/* Shift the line start to 0x____0 on entry, restore it for Ascii */
view->start_save = view->start_display;
view->start_display -= view->start_display % view->bytes_per_line;
view->edit_cursor = view->start_display;
view->widget.options |= W_WANT_CURSOR;
view->widget.parent->raw = 1;
} else {
view->start_display = view->start_save;
view->widget.parent->raw = 0;
view->widget.options &= ~W_WANT_CURSOR;
}
altered_hex_mode = 1;
get_bottom_first (view, 1, 1);
view_labels (view);
view->dirty++;
view_update (view);
}
/* Both views */
void
toggle_hexedit_mode(WView *view)
{
view->hexedit_mode = 1 - view->hexedit_mode;
}
/* Both views */
void
goto_line (WView *view)
{
char *line, prompt [100];
int i, oldline = 1;
int saved_wrap_mode = view->wrap_mode;
view->wrap_mode = 0;
for (i = view->first; i < view->start_display; i++)
if (get_byte (view, i) == '\n')
oldline ++;
sprintf (prompt, _(" The current line number is %d.\n"
" Enter the new line number:"), oldline);
line = input_dialog (_(" Goto line "), prompt, "");
if (line){
if (*line){
move_to_top (view);
view_move_forward (view, atoi (line) - 1);
}
free (line);
}
view->dirty++;
view->wrap_mode = saved_wrap_mode;
view_update (view);
}
/* Both views */
void
regexp_search (WView *view, int direction)
{
char *regexp = "";
static char *old = 0;
/* This is really an F6 key handler */
if (view->hex_mode){
/* Save it without a confirmation prompt */
save_edit_changes(view);
return;
}
regexp = old ? old : regexp;
regexp = input_dialog (_(" Search "), _(" Enter regexp:"), regexp);
if ((!regexp) || (!*regexp)){
return;
}
if (old)
free (old);
old = regexp;
#if 0
/* Mhm, do we really need to load all the file in the core? */
if (view->bytes_read < view->last_byte)
get_byte (view, view->last_byte-1);/* Get the whole file in to memory */
#endif
view->direction = direction;
do_regexp_search (view, regexp);
view->last_search = do_regexp_search;
}
void
regexp_search_cmd (WView *view)
{
regexp_search (view, 1);
}
/* Both views */
void
normal_search (WView *view, int direction)
{
static char *old;
char *exp = "";
exp = old ? old : exp;
exp = input_dialog (_(" Search "), _(" Enter search string:"), exp);
if ((!exp) || (!*exp)){
return;
}
if (old)
free (old);
old = exp;
view->direction = direction;
do_normal_search (view, exp);
view->last_search = do_normal_search;
}
void
normal_search_cmd (WView *view)
{
normal_search (view, 1);
}
void
change_viewer (WView *view)
{
char *s;
char *t;
if (*view->filename) {
altered_magic_flag = 1;
view->viewer_magic_flag = !view->viewer_magic_flag;
s = strdup (view->filename);
if (view->command)
t = strdup (view->command);
else
t = 0;
view_done (view);
view_init (view, t, s, 0);
free (s);
if (t)
free (t);
view_labels (view);
view->dirty++;
view_update (view);
}
}
void
change_nroff (WView *view)
{
view->viewer_nroff_flag = !view->viewer_nroff_flag;
altered_nroff_flag = 1;
view_labels (view);
view->dirty++;
view_update (view);
}
/* Real view only */
static void
view_quit_cmd (WView *view)
{
if (view_ok_to_quit (view))
dlg_stop (view->widget.parent);
}
/* Both views */
void
view_labels (WView *view)
{
Dlg_head *h = view->widget.parent;
define_label (h, (Widget *) view, 1, _("Help"), help_cmd);
my_define (h, 10, _("Quit"), view_quit_cmd, view);
my_define (h, 4, view->hex_mode ? _("Ascii"): _("Hex"), toggle_hex_mode, view);
my_define (h, 5, _("Line"), goto_line, view);
my_define (h, 6, view->hex_mode ? _("Save") : _("RxSrch"), regexp_search_cmd, view);
my_define (h, 2, view->hex_mode ? view->hexedit_mode ?
view->view_side == view_side_left ? _("EdText") : _("EdHex") :
view->growing_buffer ? "" : _("Edit") :
view->wrap_mode ? _("UnWrap") : _("Wrap"),
toggle_wrap_mode, view);
my_define (h, 7, view->hex_mode ? _("HxSrch") : _("Search"),
normal_search_cmd, view);
my_define (h, 8, view->viewer_magic_flag ? _("Raw") : _("Parse"),
change_viewer, view);
if (!view->have_frame){
my_define (h, 9, view->viewer_nroff_flag ? _("Unform") : _("Format"),
change_nroff, view);
my_define (h, 3, _("Quit"), view_quit_cmd, view);
}
redraw_labels (h, (Widget *) view);
}
/* Both views */
static int
check_left_right_keys (WView *view, int c)
{
if (c == KEY_LEFT)
move_left (view);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -