diff --git a/buffer.c b/buffer.c index fa60b10..be9e743 100644 --- a/buffer.c +++ b/buffer.c @@ -579,6 +579,7 @@ void eb_free(EditBuffer **bp) eb_free_style_buffer(b); + qe_free(&b->saved_data); qe_free(bp); } } diff --git a/display.c b/display.c index ece56f0..0fb2b4d 100644 --- a/display.c +++ b/display.c @@ -249,6 +249,14 @@ static QEFont dummy_font; static QEFont *font_cache[FONT_CACHE_SIZE]; static int font_cache_timestamp = 0; +void free_font_cache(QEditScreen *s) +{ + int i; + for (i = 0; i < FONT_CACHE_SIZE; i++) { + close_font(s, &font_cache[i]); + } +} + QEFont *select_font(QEditScreen *s, int style, int size) { QEFont *fc; diff --git a/display.h b/display.h index 2421d38..54a86ae 100644 --- a/display.h +++ b/display.h @@ -248,8 +248,8 @@ void fill_rectangle(QEditScreen *s, void set_clip_rectangle(QEditScreen *s, CSSRect *r); void push_clip_rectangle(QEditScreen *s, CSSRect *or, CSSRect *r); +void free_font_cache(QEditScreen *s); QEFont *select_font(QEditScreen *s, int style, int size); - static inline QEFont *lock_font(__unused__ QEditScreen *s, QEFont *font) { if (font && font->refcount) font->refcount++; diff --git a/qe.c b/qe.c index e2e1849..927ca6c 100644 --- a/qe.c +++ b/qe.c @@ -72,6 +72,9 @@ static QEditScreen global_screen; static int screen_width = 0; static int screen_height = 0; static int no_init_file; +#ifndef CONFIG_TINY +static int free_everything; +#endif static const char *user_option; /* mode handling */ @@ -80,7 +83,6 @@ void qe_register_mode(ModeDef *m) { QEmacsState *qs = &qe_state; ModeDef **p; - CmdDef *def; /* register mode in mode list (at end) */ p = &qs->first_mode; @@ -107,6 +109,7 @@ void qe_register_mode(ModeDef *m) if (!(m->mode_flags & MODEF_NOCMD)) { char buf[64]; int size; + CmdDef *def; /* lower case convert for C mode, Perl... */ qe_strtolower(buf, sizeof(buf) - 10, m->name); @@ -121,6 +124,7 @@ void qe_register_mode(ModeDef *m) def->sig = CMD_ESs; def->val = 0; def->action.ESs = do_set_mode; + def[1].val = 1; /* flag as allocated for free-all */ qe_register_cmd_table(def, NULL); } } @@ -4155,7 +4159,7 @@ void do_define_kbd_macro(EditState *s, const char *name, const char *keys, def->sig = CMD_ESs; def->val = 0; def->action.ESs = do_execute_macro_keys; - + def[1].val = 1; /* flag as allocated for free-all */ qe_register_cmd_table(def, NULL); do_set_key(s, key_bind, name, 0); } @@ -4549,6 +4553,7 @@ void switch_to_buffer(EditState *s, EditBuffer *b) EditBuffer *b1; EditState *e; ModeSavedData *saved_data, **psaved_data; + int saved_data_allocated = 0; ModeDef *mode; /* remove region hilite */ @@ -4572,14 +4577,16 @@ void switch_to_buffer(EditState *s, EditBuffer *b) * - otherwise, save the mode data in the buffer. * CG: Should free previous such data ? */ - if (b1->flags & BF_TRANSIENT) { - eb_free(&b1); - } else { + if (!(b1->flags & BF_TRANSIENT)) { + qe_free(&b1->saved_data); b1->saved_data = s->mode->mode_save_data(s); } } /* now we can close the mode */ edit_set_mode(s, NULL); + if (b1->flags & BF_TRANSIENT) { + eb_free(&b1); + } } /* now we can switch ! */ @@ -4595,6 +4602,7 @@ void switch_to_buffer(EditState *s, EditBuffer *b) if (e) { psaved_data = NULL; saved_data = e->mode->mode_save_data(e); + saved_data_allocated = 1; } else { psaved_data = &b->saved_data; saved_data = *psaved_data; @@ -4608,6 +4616,8 @@ void switch_to_buffer(EditState *s, EditBuffer *b) /* open it ! */ edit_set_mode_full(s, mode, saved_data, NULL); + if (saved_data_allocated) + qe_free(&saved_data); } } @@ -4732,6 +4742,7 @@ void edit_close(EditState *s) if (qs->active_window == s) qs->active_window = qs->first_window; + qe_free(&s->mode_data); qe_free(&s->prompt); qe_free(&s->line_shadow); qe_free(&s); @@ -5853,6 +5864,7 @@ static void quit_examine_buffers(QuitState *is) edit_display(&qe_state); dpy_flush(&global_screen); } else { + qe_free(&is); url_exit(); } } @@ -7719,6 +7731,10 @@ static CmdOptionDef cmd_options[] = { { .func_arg = set_user_option }}, { "version", "V", NULL, 0, "display version information and exit", { .func_noarg = show_version }}, +#ifndef CONFIG_TINY + { "free-all", NULL, NULL, CMD_OPT_BOOL, "free all structures upon exit", + { .int_ptr = &free_everything }}, +#endif { NULL, NULL, NULL, 0, NULL, { NULL }}, }; @@ -8040,7 +8056,65 @@ int main(int argc, char **argv) #ifdef CONFIG_ALL_KMAPS unload_input_methods(); #endif +#ifdef CONFIG_UNICODE_JOIN + unload_ligatures(); +#endif +#ifndef CONFIG_TINY + if (free_everything) { + /* free all structures for valgrind */ + QEmacsState *qs = &qe_state; + while (qs->input_methods) { + InputMethod *p = qs->input_methods; + qs->input_methods = p->next; + if (p->data) + qe_free(&p); + } + while (qs->first_window) { + EditState *e = qs->first_window; + edit_close(e); + } + while (qs->first_buffer) { + EditBuffer *b = qs->first_buffer; + eb_free(&b); + } + while (qs->first_cmd) { + CmdDef *d = qs->first_cmd; + CmdDef *d1 = d; + while (d1->name) + d1++; + qs->first_cmd = d1->action.next; + /* free xxx-mode commands and macros */ + if (d->name && !d[1].name && d[1].val) { + qe_free((char **)&d->name); + qe_free(&d); + } + } + while (qs->first_key) { + KeyDef *p = qs->first_key; + qs->first_key = p->next; + qe_free(&p); + } + while (qs->first_mode) { + ModeDef *m = qs->first_mode; + qs->first_mode = m->next; + + while (m->first_key) { + KeyDef *p = m->first_key; + m->first_key = p->next; + qe_free(&p); + } + } + while (qs->first_completion) { + CompletionEntry *cp = qs->first_completion; + qs->first_completion = cp->next; + qe_free(&cp); + } + css_free_colors(); + free_font_cache(&global_screen); + } +#endif dpy_close(&global_screen); + return 0; } diff --git a/qe.h b/qe.h index 539cc72..158d8a4 100644 --- a/qe.h +++ b/qe.h @@ -315,6 +315,7 @@ int to_hex(int key); void color_completion(CompleteState *cp); int css_define_color(const char *name, const char *value); int css_get_color(QEColor *color_ptr, const char *p); +void css_free_colors(void); int css_get_font_family(const char *str); void css_union_rect(CSSRect *a, const CSSRect *b); static inline int css_is_null_rect(const CSSRect *a) { @@ -561,6 +562,7 @@ int unicode_to_glyphs(unsigned int *dst, unsigned int *char_to_glyph_pos, int dst_size, unsigned int *src, int src_size, int reverse); int load_ligatures(void); +void unload_ligatures(void); /* qe event handling */ diff --git a/shell.c b/shell.c index 51ff13b..3eff589 100644 --- a/shell.c +++ b/shell.c @@ -1328,6 +1328,7 @@ static void shell_close(EditBuffer *b) while (waitpid(s->pid, &status, 0) != s->pid) continue; } + set_pid_handler(s->pid, NULL, NULL); s->pid = -1; } if (s->pty_fd >= 0) { diff --git a/tty.c b/tty.c index 19d2daf..b7dc5fd 100644 --- a/tty.c +++ b/tty.c @@ -241,6 +241,8 @@ static int tty_term_init(QEditScreen *s, static void tty_term_close(QEditScreen *s) { + TTYState *ts = s->priv_data; + fcntl(fileno(s->STDIN), F_SETFL, 0); #if 0 /* go to the last line */ @@ -258,6 +260,9 @@ static void tty_term_close(QEditScreen *s) ); #endif fflush(s->STDOUT); + + qe_free(&ts->screen); + qe_free(&ts->line_updated); } static void tty_term_exit(void) @@ -290,12 +295,12 @@ static void tty_resize(__unused__ int sig) count = s->width * s->height; size = count * sizeof(TTYChar); /* screen buffer + shadow buffer + extra slot for loop guard */ - qe_realloc(&ts->screen, size * 2 + 1); + qe_realloc(&ts->screen, size * 2 + sizeof(TTYChar)); qe_realloc(&ts->line_updated, s->height); ts->screen_size = count; /* Erase shadow buffer to impossible value */ - memset(ts->screen + count, 0xFF, size); + memset(ts->screen + count, 0xFF, size + sizeof(TTYChar)); /* Fill screen buffer with black spaces */ tc = TTYCHAR_DEFAULT; for (i = 0; i < count; i++) { diff --git a/unicode_join.c b/unicode_join.c index dd4d5ee..41fdf5a 100644 --- a/unicode_join.c +++ b/unicode_join.c @@ -93,6 +93,13 @@ int load_ligatures(void) return -1; } +void unload_ligatures(void) +{ + qe_free(&subst1); + qe_free(&ligature2); + qe_free(&ligature_long); +} + static int find_ligature(int l1, int l2) { int a, b, m, v1, v2; diff --git a/util.c b/util.c index cb6fa42..a7ae956 100644 --- a/util.c +++ b/util.c @@ -1152,6 +1152,18 @@ int css_define_color(const char *name, const char *value) return 0; } +void css_free_colors(void) +{ + if (qe_colors != default_colors) { + while (nb_qe_colors > nb_default_colors) { + nb_qe_colors--; + qe_free((char **)&qe_colors[nb_qe_colors].name); + } + qe_free(&qe_colors); + qe_colors = (ColorDef *)default_colors; + } +} + /* XXX: make HTML parsing optional ? */ int css_get_color(QEColor *color_ptr, const char *p) {