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
|