aboutsummaryrefslogtreecommitdiff
path: root/config/markdown_plugin.c
blob: ded0e1cd6f0248c890b26f0e20cb8a82e4e7b2ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "ecex.h"

#define MD_TEXT_TITLE 1

typedef struct md_state {
    ecex_t *ed;
} md_state_t;

static int md_render(ecex_t *ed, buffer_t *buffer, ecex_draw_context_t *ctx, void *userdata) {
    md_state_t *state = (md_state_t *)userdata;
    int draw_count;
    int line_count;
    int scroll;
    int y;
    int h;
    int line_h;
    int in_code = 0;
    int i;

    if (!ed || !buffer || !ctx || !state) return 0;

    draw_count = ecex_var_i32(ed, state, "draw_count", 0) + 1;
    ecex_var_i32_set_scalar(ed, state, "draw_count", draw_count);
    if (draw_count <= 2 || (draw_count % 120) == 0) {
        ecex_log_int("markdown_plugin_draw: count=", draw_count);
    }

    line_count = ecex_buffer_line_count_i(buffer);
    ecex_log_int("markdown_plugin_draw: line_count=", line_count);
    if (line_count < 0) line_count = 0;

    ecex_text_set_buffer_title(ed, state, MD_TEXT_TITLE, buffer);
    ecex_draw_markdown_canvas_auto_i(ctx, state, MD_TEXT_TITLE);

    y = ecex_markdown_body_y_i(ctx);
    h = ecex_draw_context_height_i(ctx);
    line_h = ecex_draw_context_line_height_i(ctx);
    scroll = ecex_buffer_scroll_line(buffer);
    if (scroll < 0) scroll = 0;
    if (scroll > line_count) scroll = line_count;

    for (i = scroll; i < line_count && y < h - line_h; ++i) {
        int packed;
        int advance;
        if (i < scroll + 4) ecex_log_int("markdown_plugin_draw: host line=", i);
        packed = ecex_markdown_draw_line_from_buffer_i(ctx, state, buffer, i, y, in_code);
        in_code = (packed & 0x10000) ? 1 : 0;
        advance = packed & 0xffff;
        if (advance <= 0) advance = line_h;
        y += advance;
    }

    return 0;
}

static void md_free_state(void *userdata) {
    md_state_t *state = (md_state_t *)userdata;
    ecex_t *ed;
    if (!state) return;
    ed = state->ed;
    ecex_text_free_owner(ed, state);
    ecex_var_free_owner(ed, state);
    ecex_object_free(ed, state);
}

static int md_view_buffer(ecex_t *ed, buffer_t *buffer) {
    md_state_t *state;
    if (!ed || !buffer) return -1;
    if (ecex_buffer_has_renderer(buffer)) ecex_buffer_clear_renderer(buffer);

    state = (md_state_t *)ecex_object_calloc(ed, 1, sizeof(*state));
    if (!state) return -1;
    state->ed = ed;

    if (ecex_buffer_set_renderer(buffer, md_render, state, md_free_state, ECEX_RENDER_REPLACE_CONTENT) != 0) {
        ecex_object_free(ed, state);
        return -1;
    }
    ecex_buffer_set_major_mode_by_name(ed, buffer, "markdown-mode");
    return 0;
}

static int md_file_handler(ecex_t *ed, buffer_t *buffer) {
    if (!buffer) return -1;
    if (ecex_buffer_has_renderer(buffer)) return 0;
    return md_view_buffer(ed, buffer);
}

static int cmd_markdown_view(ecex_t *ed) {
    return md_view_buffer(ed, ecex_current_buffer(ed));
}

static int cmd_markdown_source(ecex_t *ed) {
    buffer_t *buffer = ecex_current_buffer(ed);
    if (!buffer) return -1;
    if (ecex_buffer_has_renderer(buffer)) ecex_buffer_clear_renderer(buffer);
    ecex_buffer_set_major_mode_by_name(ed, buffer, "markdown-mode");
    return 0;
}

static int cmd_markdown_toggle(ecex_t *ed) {
    buffer_t *buffer = ecex_current_buffer(ed);
    if (!buffer) return -1;
    if (ecex_buffer_has_renderer(buffer)) return cmd_markdown_source(ed);
    return md_view_buffer(ed, buffer);
}

int ecex_markdown_plugin(ecex_t *ed) {
    ECEX_CONFIG_MODE("markdown-mode");
    ECEX_CONFIG_COMMAND("markdown-view", cmd_markdown_view);
    ECEX_CONFIG_COMMAND("markdown-source", cmd_markdown_source);
    ECEX_CONFIG_COMMAND("markdown-toggle", cmd_markdown_toggle);
    ECEX_CONFIG_MODE_BIND("markdown-mode", "C-c C-c", "markdown-toggle");
    ECEX_CONFIG_MODE_BIND("markdown-mode", "C-c C-s", "markdown-source");
    ecex_register_file_handler(ed, ".md", md_file_handler);
    ecex_register_file_handler(ed, ".markdown", md_file_handler);
    ecex_register_file_handler(ed, ".mdown", md_file_handler);
    ecex_register_file_handler(ed, ".mkd", md_file_handler);
    return 0;
}

#ifndef ECEX_NO_STANDALONE_CONFIG
ECEX_CONFIG_BEGIN
    ECEX_CONFIG_INCLUDE(ecex_markdown_plugin);
ECEX_CONFIG_END
#endif