Beispiel #1
0
/**
 * Move up.
 *
 * Unwrap mode: Piece of cake. Wrap mode: If we'd walk back more than the current line offset
 * within the paragraph, we need to jump back to the previous paragraph and compute its height to
 * see if we start from that paragraph, and repeat this if necessary. Once we're within the desired
 * paragraph, we still need to format it from its beginning to know the state.
 *
 * See the top of this file for comments about MAX_BACKWARDS_WALK_IN_PARAGRAPH.
 *
 * force_max is a nice protection against the rare extreme case that the file underneath us
 * changes, we don't want to endlessly consume a file of maybe full of zeros upon moving upwards.
 */
void
mcview_ascii_move_up (WView * view, off_t lines)
{
    if (!view->text_wrap_mode)
    {
        while (lines-- != 0)
            view->dpy_start = mcview_bol (view, view->dpy_start - 1, 0);
        view->dpy_paragraph_skip_lines = 0;
        view->dpy_wrap_dirty = TRUE;
    }
    else
    {
        int i;

        while (lines > view->dpy_paragraph_skip_lines)
        {
            /* We need to go back to the previous paragraph. */
            if (view->dpy_start == 0)
            {
                /* Oops, we're already in the first paragraph. */
                view->dpy_paragraph_skip_lines = 0;
                mcview_state_machine_init (&view->dpy_state_top, 0);
                return;
            }
            lines -= view->dpy_paragraph_skip_lines;
            view->force_max = view->dpy_start;
            view->dpy_start =
                mcview_bol (view, view->dpy_start - 1,
                            view->dpy_start - MAX_BACKWARDS_WALK_IN_PARAGRAPH);
            mcview_state_machine_init (&view->dpy_state_top, view->dpy_start);
            /* This is a tricky way of denoting that we're at the end of the paragraph.
             * Normally we'd jump to the next paragraph and reset paragraph_skip_lines. But for
             * walking backwards this is exactly what we need. */
            view->dpy_paragraph_skip_lines =
                mcview_display_paragraph (view, &view->dpy_state_top, view->data_area.height);
            view->force_max = -1;
        }

        /* Okay, we have have dpy_start pointing to the desired paragraph, and we still need to
         * walk back "lines" lines from the current "dpy_paragraph_skip_lines" offset. We can't do
         * that, so walk from the beginning of the paragraph. */
        mcview_state_machine_init (&view->dpy_state_top, view->dpy_start);
        view->dpy_paragraph_skip_lines -= lines;
        for (i = 0; i < view->dpy_paragraph_skip_lines; i++)
            mcview_display_line (view, &view->dpy_state_top, -1, NULL, NULL);
    }
}
Beispiel #2
0
Datei: lib.c Projekt: iNode/mc
void
mcview_toggle_wrap_mode (mcview_t * view)
{
    if (view->text_wrap_mode)
        view->dpy_start = mcview_bol (view, view->dpy_start, 0);
    view->text_wrap_mode = !view->text_wrap_mode;
    view->dpy_bbar_dirty = TRUE;
    view->dirty++;
}
Beispiel #3
0
Datei: move.c Projekt: ryanlee/mc
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);
}
Beispiel #4
0
Datei: move.c Projekt: ryanlee/mc
void
mcview_moveto_bol (mcview_t * view)
{
    if (view->hex_mode)
    {
        view->hex_cursor -= view->hex_cursor % view->bytes_per_line;
    }
    else if (!view->text_wrap_mode)
    {
        view->dpy_start = mcview_bol (view, view->dpy_start, 0);
    }
    view->dpy_text_column = 0;
    mcview_movement_fixups (view, TRUE);
}
Beispiel #5
0
Datei: move.c Projekt: ryanlee/mc
void
mcview_moveto_match (mcview_t * view)
{
    off_t offset;

    offset = view->search_start;

    if (view->hex_mode)
    {
        view->hex_cursor = offset;
        view->dpy_start = offset - offset % view->bytes_per_line;
    }
    else
    {
        view->dpy_start = mcview_bol (view, offset, 0);
    }

    mcview_scroll_to_cursor (view);
    view->dirty++;
}
Beispiel #6
0
Datei: lib.c Projekt: iNode/mc
void
mcview_toggle_hex_mode (mcview_t * view)
{
    view->hex_mode = !view->hex_mode;

    if (view->hex_mode)
    {
        view->hex_cursor = view->dpy_start;
        view->dpy_start = mcview_offset_rounddown (view->dpy_start, view->bytes_per_line);
        widget_want_cursor (WIDGET (view), TRUE);
    }
    else
    {
        view->dpy_start = mcview_bol (view, view->hex_cursor, 0);
        view->hex_cursor = view->dpy_start;
        widget_want_cursor (WIDGET (view), FALSE);
    }
    mcview_altered_hex_mode = 1;
    view->dpy_bbar_dirty = TRUE;
    view->dirty++;
}
Beispiel #7
0
void
mcview_moveto_match (WView * view)
{
    if (view->mode_flags.hex)
    {
        view->hex_cursor = view->search_start;
        view->hexedit_lownibble = FALSE;
        view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
        view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
        view->dpy_paragraph_skip_lines = 0;
        view->dpy_wrap_dirty = TRUE;
    }
    else
    {
        view->dpy_start = mcview_bol (view, view->search_start, 0);
        view->dpy_paragraph_skip_lines = 0;
        view->dpy_wrap_dirty = TRUE;
    }

    mcview_scroll_to_cursor (view);
    view->dirty++;
}
Beispiel #8
0
gboolean
mcview_dialog_goto (WView * view, off_t * offset)
{
    typedef enum
    {
        MC_VIEW_GOTO_LINENUM = 0,
        MC_VIEW_GOTO_PERCENT = 1,
        MC_VIEW_GOTO_OFFSET_DEC = 2,
        MC_VIEW_GOTO_OFFSET_HEX = 3
    } mcview_goto_type_t;

    const char *mc_view_goto_str[] = {
        N_("&Line number"),
        N_("Pe&rcents"),
        N_("&Decimal offset"),
        N_("He&xadecimal offset")
    };

    static mcview_goto_type_t current_goto_type = MC_VIEW_GOTO_LINENUM;

    size_t num_of_types;
    char *exp = NULL;
    int qd_result;
    gboolean res;

    num_of_types = G_N_ELEMENTS (mc_view_goto_str);

#ifdef ENABLE_NLS
    {
        size_t i;

        for (i = 0; i < num_of_types; i++)
            mc_view_goto_str[i] = _(mc_view_goto_str[i]);
    }
#endif

    {
        quick_widget_t quick_widgets[] = {
            /* *INDENT-OFF* */
            QUICK_INPUT (INPUT_LAST_TEXT, MC_HISTORY_VIEW_GOTO, &exp, NULL,
                         FALSE, FALSE, INPUT_COMPLETE_NONE),
            QUICK_RADIO (num_of_types, (const char **) mc_view_goto_str, (int *) &current_goto_type,
                         NULL),
            QUICK_BUTTONS_OK_CANCEL,
            QUICK_END
            /* *INDENT-ON* */
        };

        quick_dialog_t qdlg = {
            -1, -1, 40,
            N_("Goto"), "[Input Line Keys]",
            quick_widgets, NULL, NULL
        };

        /* run dialog */
        qd_result = quick_dialog (&qdlg);
    }

    *offset = -1;

    /* check input line value */
    res = (qd_result != B_CANCEL && exp != NULL && exp[0] != '\0');
    if (res)
    {
        int base = (current_goto_type == MC_VIEW_GOTO_OFFSET_HEX) ? 16 : 10;
        off_t addr;
        char *error;

        addr = (off_t) g_ascii_strtoll (exp, &error, base);
        if ((*error == '\0') && (addr >= 0))
        {
            switch (current_goto_type)
            {
            case MC_VIEW_GOTO_LINENUM:
                /* Line number entered by user is 1-based. */
                if (addr > 0)
                    addr--;
                mcview_coord_to_offset (view, offset, addr, 0);
                *offset = mcview_bol (view, *offset, 0);
                break;
            case MC_VIEW_GOTO_PERCENT:
                if (addr > 100)
                    addr = 100;
                /* read all data from pipe to get real size */
                if (view->growbuf_in_use)
                    mcview_growbuf_read_all_data (view);
                *offset = addr * mcview_get_filesize (view) / 100;
                if (!view->mode_flags.hex)
                    *offset = mcview_bol (view, *offset, 0);
                break;
            case MC_VIEW_GOTO_OFFSET_DEC:
            case MC_VIEW_GOTO_OFFSET_HEX:
                if (!view->mode_flags.hex)
                {
                    if (view->growbuf_in_use)
                        mcview_growbuf_read_until (view, addr);

                    *offset = mcview_bol (view, addr, 0);
                }
                else
                {
                    /* read all data from pipe to get real size */
                    if (view->growbuf_in_use)
                        mcview_growbuf_read_all_data (view);

                    *offset = addr;
                    addr = mcview_get_filesize (view);
                    if (*offset > addr)
                        *offset = addr;
                }
                break;
            default:
                *offset = 0;
                break;
            }
        }
    }

    g_free (exp);
    return res;
}
Beispiel #9
0
gboolean
mcview_load (mcview_t * view, const char *command, const char *file, int start_line)
{
    gboolean retval = FALSE;
    vfs_path_t *vpath = NULL;

#ifdef HAVE_ASSERT_H
    assert (view->bytes_per_line != 0);
#endif

    view->filename_vpath = vfs_path_from_str (file);

    /* get working dir */
    if (file != NULL && file[0] != '\0')
    {
        vfs_path_free (view->workdir_vpath);

        if (!g_path_is_absolute (file))
        {
            vfs_path_t *p;

            p = vfs_path_clone (vfs_get_raw_current_dir ());
            view->workdir_vpath = vfs_path_append_new (p, file, (char *) NULL);
            vfs_path_free (p);
        }
        else
        {
            /* try extract path form filename */
            const char *fname;
            char *dir;

            fname = x_basename (file);
            dir = g_strndup (file, (size_t) (fname - file));
            view->workdir_vpath = vfs_path_from_str (dir);
            g_free (dir);
        }
    }

    if (!mcview_is_in_panel (view))
        view->dpy_text_column = 0;

    mcview_set_codeset (view);

    if (command != NULL && (view->magic_mode || file == NULL || file[0] == '\0'))
        retval = mcview_load_command_output (view, command);
    else if (file != NULL && file[0] != '\0')
    {
        int fd;
        char tmp[BUF_MEDIUM];
        struct stat st;

        /* Open the file */
        vpath = vfs_path_from_str (file);
        fd = mc_open (vpath, O_RDONLY | O_NONBLOCK);
        if (fd == -1)
        {
            g_snprintf (tmp, sizeof (tmp), _("Cannot open \"%s\"\n%s"),
                        file, unix_error_string (errno));
            mcview_show_error (view, tmp);
            vfs_path_free (view->filename_vpath);
            view->filename_vpath = NULL;
            vfs_path_free (view->workdir_vpath);
            view->workdir_vpath = NULL;
            goto finish;
        }

        /* Make sure we are working with a regular file */
        if (mc_fstat (fd, &st) == -1)
        {
            mc_close (fd);
            g_snprintf (tmp, sizeof (tmp), _("Cannot stat \"%s\"\n%s"),
                        file, unix_error_string (errno));
            mcview_show_error (view, tmp);
            vfs_path_free (view->filename_vpath);
            view->filename_vpath = NULL;
            vfs_path_free (view->workdir_vpath);
            view->workdir_vpath = NULL;
            goto finish;
        }

        if (!S_ISREG (st.st_mode))
        {
            mc_close (fd);
            mcview_show_error (view, _("Cannot view: not a regular file"));
            vfs_path_free (view->filename_vpath);
            view->filename_vpath = NULL;
            vfs_path_free (view->workdir_vpath);
            view->workdir_vpath = NULL;
            goto finish;
        }

        if (st.st_size == 0 || mc_lseek (fd, 0, SEEK_SET) == -1)
        {
            /* Must be one of those nice files that grow (/proc) */
            mcview_set_datasource_vfs_pipe (view, fd);
        }
        else
        {
            int type;

            type = get_compression_type (fd, file);

            if (view->magic_mode && (type != COMPRESSION_NONE))
            {
                char *tmp_filename;
                vfs_path_t *vpath1;
                int fd1;

                tmp_filename = g_strconcat (file, decompress_extension (type), (char *) NULL);
                vpath1 = vfs_path_from_str (tmp_filename);
                fd1 = mc_open (vpath1, O_RDONLY | O_NONBLOCK);
                if (fd1 == -1)
                {
                    g_snprintf (tmp, sizeof (tmp), _("Cannot open \"%s\" in parse mode\n%s"),
                                file, unix_error_string (errno));
                    mcview_show_error (view, tmp);
                }
                else
                {
                    mc_close (fd);
                    fd = fd1;
                    mc_fstat (fd, &st);
                }
                vfs_path_free (vpath1);

                g_free (tmp_filename);
            }
            mcview_set_datasource_file (view, fd, &st);
        }
        retval = TRUE;
    }

  finish:
    view->command = g_strdup (command);
    view->dpy_start = 0;
    view->search_start = 0;
    view->search_end = 0;
    view->dpy_text_column = 0;

    mcview_compute_areas (view);
    mcview_update_bytes_per_line (view);

    if (mcview_remember_file_position && view->filename_vpath != NULL && start_line == 0)
    {
        long line, col;
        off_t new_offset, max_offset;

        load_file_position (view->filename_vpath, &line, &col, &new_offset, &view->saved_bookmarks);
        max_offset = mcview_get_filesize (view) - 1;
        if (max_offset < 0)
            new_offset = 0;
        else
            new_offset = min (new_offset, max_offset);
        if (!view->hex_mode)
            view->dpy_start = mcview_bol (view, new_offset, 0);
        else
        {
            view->dpy_start = new_offset - new_offset % view->bytes_per_line;
            view->hex_cursor = new_offset;
        }
    }
    else if (start_line > 0)
        mcview_moveto (view, start_line - 1, 0);

    view->hexedit_lownibble = FALSE;
    view->hexview_in_text = FALSE;
    view->change_list = NULL;
    vfs_path_free (vpath);
    return retval;
}
Beispiel #10
0
gboolean
mcview_dialog_goto (mcview_t * view, off_t * offset)
{
    typedef enum
    {
        MC_VIEW_GOTO_LINENUM = 0,
        MC_VIEW_GOTO_PERCENT = 1,
        MC_VIEW_GOTO_OFFSET_DEC = 2,
        MC_VIEW_GOTO_OFFSET_HEX = 3
    } mcview_goto_type_t;

    const char *mc_view_goto_str[] = {
        N_("&Line number (decimal)"),
        N_("Pe&rcents"),
        N_("&Decimal offset"),
        N_("He&xadecimal offset")
    };

    const int goto_dlg_height = 12;
    int goto_dlg_width = 40;

    static mcview_goto_type_t current_goto_type = MC_VIEW_GOTO_LINENUM;

    size_t i;

    size_t num_of_types = sizeof (mc_view_goto_str) / sizeof (mc_view_goto_str[0]);
    char *exp = NULL;
    int qd_result;
    gboolean res = FALSE;

    QuickWidget quick_widgets[] = {
        QUICK_BUTTON (6, 10, goto_dlg_height - 3, goto_dlg_height, N_("&Cancel"), B_CANCEL, NULL),
        QUICK_BUTTON (2, 10, goto_dlg_height - 3, goto_dlg_height, N_("&OK"), B_ENTER, NULL),
        QUICK_RADIO (3, goto_dlg_width, 4, goto_dlg_height,
                     num_of_types, (const char **) mc_view_goto_str, (int *) &current_goto_type),
        QUICK_INPUT (3, goto_dlg_width, 2, goto_dlg_height,
                     INPUT_LAST_TEXT, goto_dlg_width - 6, 0, MC_HISTORY_VIEW_GOTO, &exp),
        QUICK_END
    };

    QuickDialog Quick_input = {
        goto_dlg_width, goto_dlg_height, -1, -1,
        N_("Goto"), "[Input Line Keys]",
        quick_widgets, NULL, NULL, FALSE
    };

#ifdef ENABLE_NLS
    for (i = 0; i < num_of_types; i++)
        mc_view_goto_str[i] = _(mc_view_goto_str[i]);

    quick_widgets[0].u.button.text = _(quick_widgets[0].u.button.text);
    quick_widgets[1].u.button.text = _(quick_widgets[1].u.button.text);
#endif

    /* calculate widget coordinates */
    {
        int b0_len, b1_len, len;
        const int button_gap = 2;

        /* preliminary dialog width */
        goto_dlg_width = max (goto_dlg_width, str_term_width1 (Quick_input.title) + 4);

        /* length of radiobuttons */
        for (i = 0; i < num_of_types; i++)
            goto_dlg_width = max (goto_dlg_width, str_term_width1 (mc_view_goto_str[i]) + 10);

        /* length of buttons */
        b0_len = str_term_width1 (quick_widgets[0].u.button.text) + 3;
        b1_len = str_term_width1 (quick_widgets[1].u.button.text) + 5;  /* default button */
        len = b0_len + b1_len + button_gap * 2;

        /* dialog width */
        Quick_input.xlen = max (goto_dlg_width, len + 6);

        /* correct widget coordinates */
        for (i = sizeof (quick_widgets) / sizeof (quick_widgets[0]); i > 0; i--)
            quick_widgets[i - 1].x_divisions = Quick_input.xlen;

        /* input length */
        quick_widgets[3].u.input.len = Quick_input.xlen - 6;

        /* button positions */
        quick_widgets[1].relative_x = Quick_input.xlen / 2 - len / 2;
        quick_widgets[0].relative_x = quick_widgets[1].relative_x + b1_len + button_gap;
    }

    /* run dialog */
    qd_result = quick_dialog (&Quick_input);

    *offset = -1;

    /* check input line value */
    if ((qd_result != B_CANCEL) && (exp != NULL) && (exp[0] != '\0'))
    {
        int base = (current_goto_type == MC_VIEW_GOTO_OFFSET_HEX) ? 16 : 10;
        off_t addr;
        char *error;

        res = TRUE;

        addr = strtoll (exp, &error, base);
        if ((*error == '\0') && (addr >= 0))
        {
            switch (current_goto_type)
            {
            case MC_VIEW_GOTO_LINENUM:
                mcview_coord_to_offset (view, offset, addr, 0);
                *offset = mcview_bol (view, *offset, 0);
                break;
            case MC_VIEW_GOTO_PERCENT:
                if (addr > 100)
                    addr = 100;
                *offset = addr * mcview_get_filesize (view) / 100;
                if (!view->hex_mode)
                    *offset = mcview_bol (view, *offset, 0);
                break;
            case MC_VIEW_GOTO_OFFSET_DEC:
            case MC_VIEW_GOTO_OFFSET_HEX:
                *offset = addr;
                if (!view->hex_mode)
                    *offset = mcview_bol (view, *offset, 0);
                else
                {
                    addr = mcview_get_filesize (view);
                    if (*offset > addr)
                        *offset = addr;
                }
                break;
            default:
                *offset = 0;
                break;
            }
        }
    }

    g_free (exp);
    return res;
}
Beispiel #11
0
Datei: move.c Projekt: ryanlee/mc
void
mcview_move_up (mcview_t * view, off_t lines)
{
    off_t new_offset;

    if (view->hex_mode)
    {
        off_t bytes = lines * view->bytes_per_line;
        if (view->hex_cursor >= bytes)
        {
            view->hex_cursor -= bytes;
            if (view->hex_cursor < view->dpy_start)
                view->dpy_start = mcview_offset_doz (view->dpy_start, bytes);
        }
        else
        {
            view->hex_cursor %= view->bytes_per_line;
        }
    }
    else
    {
        off_t i;

        for (i = 0; i < lines; i++)
        {
            if (view->dpy_start == 0)
                break;
            if (view->text_wrap_mode)
            {
                new_offset = mcview_bol (view, view->dpy_start, view->dpy_start - (off_t) 1);
                /* check if dpy_start == BOL or not (then new_offset = dpy_start - 1,
                 * no need to check more) */
                if (new_offset == view->dpy_start)
                {
                    size_t last_row_length;

                    new_offset = mcview_bol (view, new_offset - 1, 0);
                    last_row_length = (view->dpy_start - new_offset) % view->data_area.width;
                    if (last_row_length != 0)
                    {
                        /* if dpy_start == BOL in wrapped mode, find BOL of previous line
                         * and move down all but the last rows */
                        new_offset = view->dpy_start - (off_t) last_row_length;
                    }
                }
                else
                {
                    /* if dpy_start != BOL in wrapped mode, just move one row up;
                     * no need to check if > 0 as there is at least exactly one wrap
                     * between dpy_start and BOL */
                    new_offset = view->dpy_start - (off_t) view->data_area.width;
                }
                view->dpy_start = new_offset;
            }
            else
            {
                /* if unwrapped -> current BOL equals dpy_start, just find BOL of previous line */
                new_offset = view->dpy_start - 1;
                view->dpy_start = mcview_bol (view, new_offset, 0);
            }
        }
    }
    mcview_movement_fixups (view, TRUE);
}