Skip to content

Commit 409280c

Browse files
author
Charlie Gordon
committed
Improve mode selection and mode specific command safety
* add set-auto-mode() to (re)select best mode for buffer * add set-next-mode() on M-m to cycle appropriate buffer modes * add set-previous-mode() * add default_mode and saved_mode in buffers to improve mode switching * add dired mode probing and store st_mode in buffer to detect directories * add charset, eol_type and buffer in ModeProbeData * clean mode selection and window buffer attachment (needs more work) * compute sorted list of appropriate modes in probe_mode * convert charset and eol_type in mode_probe * add signatures in buffer priv_data to perform save casts * move BufedState to b->priv_data, protect mode specific functions add bufed_mode_probe function, cycling through modes comes back to bufed mode * move DiredState to b->priv_data, protect mode specific functions add dired_mode_probe function, cycling through modes comes back to dired mode * add heading line in dired buffer with directory spec * protect shell-mode specific functions. * restart shell in shell() command if exited * some cosmetics changes (remove useless __unused__, missing messages ...)
1 parent 411ca91 commit 409280c

File tree

9 files changed

+593
-261
lines changed

9 files changed

+593
-261
lines changed

bufed.c

+105-27
Original file line numberDiff line numberDiff line change
@@ -25,55 +25,79 @@ enum {
2525
BUFED_ALL_VISIBLE = 1
2626
};
2727

28+
static int bufed_signature;
29+
2830
typedef struct BufedState {
31+
void *signature;
2932
StringArray items;
3033
int flags;
3134
int last_index;
3235
} BufedState;
3336

3437
static ModeDef bufed_mode;
3538

39+
static BufedState *bufed_get_state(EditState *s)
40+
{
41+
BufedState *bs = s->b->priv_data;
42+
43+
if (bs && bs->signature == &bufed_signature)
44+
return bs;
45+
46+
put_status(s, "Not a bufed buffer");
47+
return NULL;
48+
}
49+
3650
static void build_bufed_list(EditState *s)
3751
{
3852
QEmacsState *qs = s->qe_state;
3953
EditBuffer *b;
40-
BufedState *hs;
54+
BufedState *bs;
4155
int last_index = list_get_pos(s);
42-
int i, flags;
56+
int i;
4357

44-
hs = s->mode_data;
58+
if (!(bs = bufed_get_state(s)))
59+
return;
4560

46-
free_strings(&hs->items);
61+
free_strings(&bs->items);
4762
for (b = qs->first_buffer; b != NULL; b = b->next) {
48-
if (!(b->flags & BF_SYSTEM) || (hs->flags & BUFED_ALL_VISIBLE))
49-
add_string(&hs->items, b->name);
63+
if (!(b->flags & BF_SYSTEM) || (bs->flags & BUFED_ALL_VISIBLE))
64+
add_string(&bs->items, b->name);
5065
}
5166

5267
/* build buffer */
5368
b = s->b;
54-
flags = b->flags;
5569
b->flags &= ~BF_READONLY;
5670
eb_delete(b, 0, b->total_size);
57-
for (i = 0; i < hs->items.nb_items; i++) {
58-
EditBuffer *b1 = eb_find(hs->items.items[i]->str);
71+
72+
for (i = 0; i < bs->items.nb_items; i++) {
73+
EditBuffer *b1 = eb_find(bs->items.items[i]->str);
5974
char flags[4];
6075
char *flagp = flags;
6176

77+
if (i == last_index) {
78+
s->offset = b->total_size;
79+
}
6280
if (b1) {
6381
if (b1->modified)
6482
*flagp++ = '*';
6583
if (b1->flags & BF_READONLY)
6684
*flagp++ = '%';
6785
}
6886
*flagp = '\0';
69-
eb_printf(b, " %-2s%-16s", flags, hs->items.items[i]->str);
87+
eb_printf(b, " %-2s%-16s", flags, bs->items.items[i]->str);
7088
if (b1) {
7189
char path[MAX_FILENAME_SIZE];
7290
const char *mode_name;
7391
EditState *e;
7492

93+
if (b1->saved_mode) {
94+
mode_name = b1->saved_mode->name;
95+
} else
7596
if (b1->saved_data) {
7697
mode_name = b1->saved_data->mode->name;
98+
} else
99+
if (b1->default_mode) {
100+
mode_name = b1->default_mode->name;
77101
} else {
78102
mode_name = "none";
79103
for (e = qs->first_window; e != NULL; e = e->next_window) {
@@ -93,15 +117,18 @@ static void build_bufed_list(EditState *s)
93117
}
94118
eb_printf(b, "\n");
95119
}
96-
b->flags = flags;
97-
s->offset = eb_goto_pos(s->b, last_index, 0);
120+
b->modified = 0;
121+
b->flags |= BF_READONLY;
98122
}
99123

100124
static EditBuffer *bufed_get_buffer(EditState *s)
101125
{
102-
BufedState *bs = s->mode_data;
126+
BufedState *bs;
103127
int index;
104128

129+
if (!(bs = bufed_get_state(s)))
130+
return NULL;
131+
105132
index = list_get_pos(s);
106133
if (index < 0 || index >= bs->items.nb_items)
107134
return NULL;
@@ -111,12 +138,15 @@ static EditBuffer *bufed_get_buffer(EditState *s)
111138

112139
static void bufed_select(EditState *s, int temp)
113140
{
114-
BufedState *bs = s->mode_data;
141+
BufedState *bs;
115142
StringItem *item;
116143
EditBuffer *b;
117144
EditState *e;
118145
int index;
119146

147+
if (!(bs = bufed_get_state(s)))
148+
return;
149+
120150
index = list_get_pos(s);
121151
if (index < 0 || index >= bs->items.nb_items)
122152
return;
@@ -137,7 +167,7 @@ static void bufed_select(EditState *s, int temp)
137167
return;
138168
}
139169
if (e) {
140-
/* delete dired window */
170+
/* delete bufed window */
141171
do_delete_window(s, 1);
142172
switch_to_buffer(e, b);
143173
} else {
@@ -175,13 +205,20 @@ static void string_selection_iterate(StringArray *cs,
175205
static void bufed_kill_item(void *opaque, StringItem *item)
176206
{
177207
EditState *s = opaque;
178-
do_kill_buffer(s, item->str);
208+
209+
/* XXX: avoid killing buffer list by mistake */
210+
if (strcmp(s->b->name, item->str))
211+
do_kill_buffer(s, item->str);
179212
}
180213

181214
static void bufed_kill_buffer(EditState *s)
182215
{
183-
BufedState *hs = s->mode_data;
184-
string_selection_iterate(&hs->items, list_get_pos(s),
216+
BufedState *bs;
217+
218+
if (!(bs = bufed_get_state(s)))
219+
return;
220+
221+
string_selection_iterate(&bs->items, list_get_pos(s),
185222
bufed_kill_item, s);
186223
build_bufed_list(s);
187224
}
@@ -209,7 +246,9 @@ static void do_list_buffers(EditState *s, int argval)
209246
e = insert_window_left(b, width, WF_MODELINE);
210247
edit_set_mode(e, &bufed_mode);
211248

212-
bs = e->mode_data;
249+
if (!(bs = bufed_get_state(e)))
250+
return;
251+
213252
if (argval != NO_ARG) {
214253
bs->flags |= BUFED_ALL_VISIBLE;
215254
build_bufed_list(e);
@@ -257,7 +296,10 @@ static void bufed_toggle_read_only(EditState *s)
257296

258297
static void bufed_refresh(EditState *s, int toggle)
259298
{
260-
BufedState *bs = s->mode_data;
299+
BufedState *bs;
300+
301+
if (!(bs = bufed_get_state(s)))
302+
return;
261303

262304
if (toggle)
263305
bs->flags ^= BUFED_ALL_VISIBLE;
@@ -274,21 +316,57 @@ static void bufed_display_hook(EditState *s)
274316
bufed_select(s, 1);
275317
}
276318

319+
static int bufed_mode_probe(ModeDef *mode, ModeProbeData *p)
320+
{
321+
if (p->b->priv_data) {
322+
BufedState *bs = p->b->priv_data;
323+
if (bs->signature == &bufed_signature)
324+
return 95;
325+
else
326+
return 0;
327+
}
328+
return 0;
329+
}
330+
331+
static void bufed_close(EditBuffer *b)
332+
{
333+
BufedState *bs = b->priv_data;
334+
335+
if (bs) {
336+
free_strings(&bs->items);
337+
}
338+
339+
qe_free(&b->priv_data);
340+
}
341+
277342
static int bufed_mode_init(EditState *s, ModeSavedData *saved_data)
278343
{
344+
BufedState *bs;
345+
279346
list_mode.mode_init(s, saved_data);
280347

281-
build_bufed_list(s);
348+
if (s->b->priv_data) {
349+
bs = s->b->priv_data;
350+
if (bs->signature != &bufed_signature)
351+
return -1;
352+
} else {
353+
/* XXX: should be allocated by buffer_load API */
354+
bs = qe_mallocz(BufedState);
355+
if (!bs)
356+
return -1;
357+
358+
bs->signature = &bufed_signature;
359+
s->b->priv_data = bs;
360+
s->b->close = bufed_close;
282361

362+
/* XXX: should be built by buffer_load API */
363+
build_bufed_list(s);
364+
}
283365
return 0;
284366
}
285367

286368
static void bufed_mode_close(EditState *s)
287369
{
288-
BufedState *bs = s->mode_data;
289-
290-
free_strings(&bs->items);
291-
292370
list_mode.mode_close(s);
293371
}
294372

@@ -315,7 +393,7 @@ static CmdDef bufed_commands[] = {
315393
"previous-line", do_up_down, -1)
316394
CMD1( 'r', 'g',
317395
"bufed-refresh", bufed_refresh, 0)
318-
CMD0( 'k', KEY_F8,
396+
CMD0( 'k', 'd',
319397
"bufed-kill-buffer", bufed_kill_buffer)
320398
CMD_DEF_END,
321399
};
@@ -332,7 +410,7 @@ static int bufed_init(void)
332410
/* CG: assuming list_mode already initialized ? */
333411
memcpy(&bufed_mode, &list_mode, sizeof(ModeDef));
334412
bufed_mode.name = "bufed";
335-
bufed_mode.instance_size = sizeof(BufedState);
413+
bufed_mode.mode_probe = bufed_mode_probe;
336414
bufed_mode.mode_init = bufed_mode_init;
337415
bufed_mode.mode_close = bufed_mode_close;
338416
/* CG: not a good idea, display hook has side effect on layout */

0 commit comments

Comments
 (0)