From c567ebcf337b96efbcb37aab5728825e601151cc Mon Sep 17 00:00:00 2001 From: Michael Jennings Date: Sat, 2 Sep 2000 04:12:16 +0000 Subject: [PATCH] Fri Sep 1 21:03:53 PDT 2000 Michael Jennings I'm working on some deallocators now. The idea is that when Eterm exits and memory debugging is on, several routines get called to free the in-use memory (menus, font cache, etc.) that we still know about. Anything left after that would be either unavoidable leaks (like environment variables...read the putenv() man page sometime...sigh) or genuine memory leaks that need fixing. I'm down to about 4.5K of leftover malloc'd memory now. Making progress.... SVN revision: 3295 --- ChangeLog | 11 ++++ libmej/libmej.h | 3 + reformat-code | 1 + src/buttons.c | 14 ++--- src/buttons.h | 2 +- src/command.c | 15 ++++- src/events.c | 48 +++++++-------- src/font.c | 118 +++++++++++++++++++++++++++++++---- src/font.h | 10 ++- src/menus.c | 161 +++++++++++++++++++++++++++++++----------------- src/menus.h | 3 + src/pixmap.c | 4 +- src/screen.c | 4 +- src/scrollbar.c | 18 +++--- 14 files changed, 292 insertions(+), 120 deletions(-) diff --git a/ChangeLog b/ChangeLog index b1858ca..79f0dba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3875,3 +3875,14 @@ Fri Sep 1 15:25:28 PDT 2000 Michael Jennings shot. ------------------------------------------------------------------------------- +Fri Sep 1 21:03:53 PDT 2000 Michael Jennings + + I'm working on some deallocators now. The idea is that when Eterm + exits and memory debugging is on, several routines get called to free + the in-use memory (menus, font cache, etc.) that we still know about. + Anything left after that would be either unavoidable leaks (like + environment variables...read the putenv() man page sometime...sigh) + or genuine memory leaks that need fixing. I'm down to about 4.5K of + leftover malloc'd memory now. Making progress.... + +------------------------------------------------------------------------------- diff --git a/libmej/libmej.h b/libmej/libmej.h index 7e2174a..7ae5807 100644 --- a/libmej/libmej.h +++ b/libmej/libmej.h @@ -98,6 +98,9 @@ #define FIXME_NOP(x) #define FIXME_BLOCK 0 +/* An "unused block" marker similar to the above. */ +#define UNUSED_BLOCK 0 + /* The basic debugging output leader. */ #if defined(__FILE__) && defined(__LINE__) # ifdef __GNUC__ diff --git a/reformat-code b/reformat-code index c2f14ce..6f39fbd 100755 --- a/reformat-code +++ b/reformat-code @@ -7,3 +7,4 @@ for i in *.c src/*.c utils/*.c ; do fi done +perl -p -i.bak -e 's/(\w+)_t (\*+)\s+/$1_t ($2)/g;' */*.[ch] diff --git a/src/buttons.c b/src/buttons.c index f238375..65b29ec 100644 --- a/src/buttons.c +++ b/src/buttons.c @@ -137,7 +137,7 @@ bbar_event_init_dispatcher(void) } unsigned char -bbar_handle_enter_notify(event_t * ev) +bbar_handle_enter_notify(event_t *ev) { button_t *b; Window unused_root, unused_child; @@ -158,7 +158,7 @@ bbar_handle_enter_notify(event_t * ev) } unsigned char -bbar_handle_leave_notify(event_t * ev) +bbar_handle_leave_notify(event_t *ev) { D_EVENTS(("bbar_handle_leave_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -172,7 +172,7 @@ bbar_handle_leave_notify(event_t * ev) } unsigned char -bbar_handle_button_press(event_t * ev) +bbar_handle_button_press(event_t *ev) { D_EVENTS(("bbar_handle_button_press(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -187,7 +187,7 @@ bbar_handle_button_press(event_t * ev) } unsigned char -bbar_handle_button_release(event_t * ev) +bbar_handle_button_release(event_t *ev) { button_t *b; Window unused_root, unused_child; @@ -214,7 +214,7 @@ bbar_handle_button_release(event_t * ev) } unsigned char -bbar_handle_motion_notify(event_t * ev) +bbar_handle_motion_notify(event_t *ev) { button_t *b; Window unused_root, unused_child; @@ -247,7 +247,7 @@ bbar_handle_motion_notify(event_t * ev) } unsigned char -bbar_dispatch_event(event_t * ev) +bbar_dispatch_event(event_t *ev) { if (buttonbar->event_data.handlers[ev->type] != NULL) { return ((buttonbar->event_data.handlers[ev->type]) (ev)); @@ -587,7 +587,7 @@ button_create(char *text) } unsigned char -button_set_icon(button_t *button, simage_t * icon) +button_set_icon(button_t *button, simage_t *icon) { ASSERT_RVAL(button != NULL, 0); ASSERT_RVAL(icon != NULL, 0); diff --git a/src/buttons.h b/src/buttons.h index fdb6f4b..027e099 100644 --- a/src/buttons.h +++ b/src/buttons.h @@ -116,7 +116,7 @@ extern unsigned char bbar_set_font(buttonbar_t *bbar, const char *fontname); extern button_t *find_button_by_text(buttonbar_t *bbar, char *text); extern button_t *find_button_by_coords(buttonbar_t *bbar, int x, int y); extern button_t *button_create(char *text); -extern unsigned char button_set_icon(button_t *button, simage_t * icon); +extern unsigned char button_set_icon(button_t *button, simage_t *icon); extern unsigned char button_set_action(button_t *button, action_type_t type, char *action); extern void bbar_select_button(buttonbar_t *bbar, button_t *button); extern void bbar_deselect_button(buttonbar_t *bbar, button_t *button); diff --git a/src/command.c b/src/command.c index f75131b..a8e11da 100644 --- a/src/command.c +++ b/src/command.c @@ -1119,7 +1119,16 @@ install_handlers(void) void clean_exit(void) { - scr_release(); +#if DEBUG >= DEBUG_MEM + if (DEBUG_LEVEL >= DEBUG_MEM) { + /* Deallocate all our crap to help find memory leaks */ + scr_release(); + menulist_clear(menu_list); + font_cache_clear(); + eterm_font_list_clear(); + } +#endif + privileges(INVOKE); #ifndef __CYGWIN32__ @@ -1471,7 +1480,7 @@ get_tty(void) } while (0) # define SHOW_CONT_CHAR(entry, name) fprintf(stderr, "%s=%#3o ", name, ttymode->c_cc[entry]) static void -debug_ttymode(ttymode_t * ttymode) +debug_ttymode(ttymode_t *ttymode) { /* c_iflag bits */ @@ -1541,7 +1550,7 @@ debug_ttymode(ttymode_t * ttymode) /* get_ttymode() */ static void -get_ttymode(ttymode_t * tio) +get_ttymode(ttymode_t *tio) { #ifdef HAVE_TERMIOS_H /* diff --git a/src/events.c b/src/events.c index 2df0126..20d6721 100644 --- a/src/events.c +++ b/src/events.c @@ -77,7 +77,7 @@ event_register_dispatcher(event_dispatcher_t func, event_dispatcher_init_t init) } void -event_dispatch(event_t * event) +event_dispatch(event_t *event) { register unsigned char i; @@ -93,7 +93,7 @@ event_dispatch(event_t * event) } void -event_data_add_mywin(event_dispatcher_data_t * data, Window win) +event_data_add_mywin(event_dispatcher_data_t *data, Window win) { ASSERT(data != NULL); @@ -110,7 +110,7 @@ event_data_add_mywin(event_dispatcher_data_t * data, Window win) } void -event_data_add_parent(event_dispatcher_data_t * data, Window win) +event_data_add_parent(event_dispatcher_data_t *data, Window win) { ASSERT(data != NULL); @@ -163,7 +163,7 @@ event_init_primary_dispatcher(void) } unsigned char -event_win_is_mywin(register event_dispatcher_data_t * data, Window win) +event_win_is_mywin(register event_dispatcher_data_t *data, Window win) { register unsigned short i; @@ -179,7 +179,7 @@ event_win_is_mywin(register event_dispatcher_data_t * data, Window win) } unsigned char -event_win_is_parent(register event_dispatcher_data_t * data, Window win) +event_win_is_parent(register event_dispatcher_data_t *data, Window win) { register unsigned short i; @@ -195,7 +195,7 @@ event_win_is_parent(register event_dispatcher_data_t * data, Window win) } unsigned char -handle_key_press(event_t * ev) +handle_key_press(event_t *ev) { #ifdef COUNT_X_EVENTS static unsigned long keypress_cnt = 0; @@ -215,7 +215,7 @@ handle_key_press(event_t * ev) } unsigned char -handle_property_notify(event_t * ev) +handle_property_notify(event_t *ev) { Atom prop; @@ -281,7 +281,7 @@ handle_property_notify(event_t * ev) } unsigned char -handle_destroy_notify(event_t * ev) +handle_destroy_notify(event_t *ev) { D_EVENTS(("handle_destroy_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -296,7 +296,7 @@ handle_destroy_notify(event_t * ev) } unsigned char -handle_client_message(event_t * ev) +handle_client_message(event_t *ev) { D_EVENTS(("handle_client_message(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -337,7 +337,7 @@ handle_client_message(event_t * ev) } unsigned char -handle_mapping_notify(event_t * ev) +handle_mapping_notify(event_t *ev) { D_EVENTS(("handle_mapping_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -348,7 +348,7 @@ handle_mapping_notify(event_t * ev) } unsigned char -handle_visibility_notify(event_t * ev) +handle_visibility_notify(event_t *ev) { D_EVENTS(("handle_visibility_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -372,7 +372,7 @@ handle_visibility_notify(event_t * ev) } unsigned char -handle_enter_notify(event_t * ev) +handle_enter_notify(event_t *ev) { D_EVENTS(("handle_enter_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -390,7 +390,7 @@ handle_enter_notify(event_t * ev) } unsigned char -handle_leave_notify(event_t * ev) +handle_leave_notify(event_t *ev) { D_EVENTS(("handle_leave_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -408,7 +408,7 @@ handle_leave_notify(event_t * ev) } unsigned char -handle_focus_in(event_t * ev) +handle_focus_in(event_t *ev) { D_EVENTS(("handle_focus_in(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -449,7 +449,7 @@ handle_focus_in(event_t * ev) } unsigned char -handle_focus_out(event_t * ev) +handle_focus_out(event_t *ev) { D_EVENTS(("handle_focus_out(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -477,7 +477,7 @@ handle_focus_out(event_t * ev) } unsigned char -handle_configure_notify(event_t * ev) +handle_configure_notify(event_t *ev) { D_EVENTS(("handle_configure_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -520,7 +520,7 @@ handle_configure_notify(event_t * ev) } unsigned char -handle_selection_clear(event_t * ev) +handle_selection_clear(event_t *ev) { D_EVENTS(("handle_selection_clear(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -530,7 +530,7 @@ handle_selection_clear(event_t * ev) } unsigned char -handle_selection_notify(event_t * ev) +handle_selection_notify(event_t *ev) { D_EVENTS(("handle_selection_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -540,7 +540,7 @@ handle_selection_notify(event_t * ev) } unsigned char -handle_selection_request(event_t * ev) +handle_selection_request(event_t *ev) { D_EVENTS(("handle_selection_request(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -550,7 +550,7 @@ handle_selection_request(event_t * ev) } unsigned char -handle_expose(event_t * ev) +handle_expose(event_t *ev) { PROF_INIT(handle_expose); D_EVENTS(("handle_expose(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -578,7 +578,7 @@ handle_expose(event_t * ev) } unsigned char -handle_button_press(event_t * ev) +handle_button_press(event_t *ev) { D_EVENTS(("handle_button_press(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -662,7 +662,7 @@ handle_button_press(event_t * ev) } unsigned char -handle_button_release(event_t * ev) +handle_button_release(event_t *ev) { D_EVENTS(("handle_button_release(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -715,7 +715,7 @@ handle_button_release(event_t * ev) } unsigned char -handle_motion_notify(event_t * ev) +handle_motion_notify(event_t *ev) { #ifdef COUNT_X_EVENTS static unsigned long motion_cnt = 0; @@ -754,7 +754,7 @@ handle_motion_notify(event_t * ev) } unsigned char -process_x_event(event_t * ev) +process_x_event(event_t *ev) { #ifdef COUNT_X_EVENTS static unsigned long event_cnt = 0; diff --git a/src/font.c b/src/font.c index db89cae..b968c36 100644 --- a/src/font.c +++ b/src/font.c @@ -59,18 +59,23 @@ static cachefont_t *font_cache_find(const char *name, unsigned char type); static void *font_cache_find_info(const char *name, unsigned char type); static unsigned char get_corner(const char *corner); +/* The eterm_font_(add|delete) functions keep track of the names of the terminal fonts + as defined in the attributes/multicharset contexts. They do NOT call the cache + routines. The caller is responsible for adding/removing fonts to/from the cache. */ void eterm_font_add(char ***plist, const char *fontname, unsigned char idx) { char **flist; D_FONT(("Adding \"%s\" at %u (%8p)\n", NONULL(fontname), (unsigned int) idx, plist)); - ASSERT(plist != NULL); - flist = *plist; + ASSERT(plist != NULL); /* plist is the address of either etfonts or etmfonts */ + /* If we're adding the font at an index we don't have yet, we must resize to fit it. */ if (idx >= font_cnt) { unsigned char new_size = sizeof(char *) * (idx + 1); + /* The below looks messy with all the cpp stuff, but it really just malloc's/realloc's + both etfonts and etmfonts at the same time to the same size, then prints some goop. */ if (etfonts) { etfonts = (char **) REALLOC(etfonts, new_size); #ifdef MULTI_CHARSET @@ -88,22 +93,25 @@ eterm_font_add(char ***plist, const char *fontname, unsigned char idx) { D_FONT((" -> Allocating font list: %u bytes at %8p\n", new_size, etfonts)); #endif } + + /* Initialize the new memory so we don't think it's got valid font info. */ MEMSET(etfonts + font_cnt, 0, sizeof(char *) * (idx - font_cnt + 1)); #ifdef MULTI_CHARSET MEMSET(etmfonts + font_cnt, 0, sizeof(char *) * (idx - font_cnt + 1)); #endif - font_cnt = idx + 1; + font_cnt = idx + 1; /* Update the font count. */ #ifdef MULTI_CHARSET flist = ((plist == &etfonts) ? (etfonts) : (etmfonts)); #else flist = etfonts; #endif } else { + flist = *plist; if (flist[idx]) { if ((flist[idx] == fontname) || (!strcasecmp(flist[idx], fontname))) { - return; + return; /* We've already got the right font. */ } - FREE(flist[idx]); + FREE(flist[idx]); /* We're replacing an old font. Get rid of the old name. */ } } flist[idx] = STRDUP(fontname); @@ -121,6 +129,25 @@ eterm_font_delete(char **flist, unsigned char idx) { flist[idx] = NULL; } +void +eterm_font_list_clear(void) +{ + unsigned char idx; + + for (idx = 0; idx < font_cnt; idx++) { + eterm_font_delete(etfonts, idx); +#ifdef MULTI_CHARSET + eterm_font_delete(etmfonts, idx); +#endif + } + FREE(etfonts); +#ifdef MULTI_CHARSET + FREE(etmfonts); +#endif +} + +/* These font caching routines keep track of all the various fonts we allocate + in the X server so that we only allocate each font once. Saves memory. */ static void font_cache_add(const char *name, unsigned char type, void *info) { @@ -128,6 +155,7 @@ font_cache_add(const char *name, unsigned char type, void *info) { D_FONT(("font_cache_add(%s, %d, %8p) called.\n", NONULL(name), type, info)); + /* Allocate the cache info for the font and store the data */ font = (cachefont_t *) MALLOC(sizeof(cachefont_t)); font->name = STRDUP(name); font->type = type; @@ -139,6 +167,8 @@ font_cache_add(const char *name, unsigned char type, void *info) { default: break; } D_FONT((" -> Created new cachefont_t struct at %p: \"%s\", %d, %p\n", font, font->name, font->type, font->fontinfo.xfontinfo)); + + /* Actually add the struct to the end of our cache linked list. */ if (font_cache == NULL) { font_cache = cur_font = font; font->next = NULL; @@ -162,10 +192,13 @@ font_cache_del(const void *info) { D_FONT(("font_cache_del(%8p) called.\n", info)); if (font_cache == NULL) { - return; + return; /* No fonts in the cache. Theoretically this should never happen, but... */ } + + /* Check the very first entry for a match. It's a special case. */ if (((font_cache->type == FONT_TYPE_X) && (font_cache->fontinfo.xfontinfo == (XFontStruct *) info))) { D_FONT((" -> Match found at font_cache (%8p). Font name is \"%s\"\n", font_cache, NONULL(font_cache->name))); + /* We've got a match. Decrement the reference count, and if it goes to 0, remove it from the cache. */ if (--(font_cache->ref_cnt) == 0) { D_FONT((" -> Reference count is now 0. Deleting from cache.\n")); current = font_cache; @@ -177,9 +210,13 @@ font_cache_del(const void *info) { D_FONT((" -> Reference count is %d. Returning.\n", font_cache->ref_cnt)); } return; +#if UNUSED_BLOCK } else if ((font_cache->type == FONT_TYPE_TTF) && (0)) { } else if ((font_cache->type == FONT_TYPE_FNLIB) && (0)) { +#endif } else { + /* Search for a match. We test current->next, not current, so that we can + update the "next" pointer of the font prior to the one we're actually deleting. */ for (current = font_cache; current->next; current = current->next) { if (((current->next->type == FONT_TYPE_X) && (current->next->fontinfo.xfontinfo == (XFontStruct *) info))) { D_FONT((" -> Match found at current->next (%8p, current == %8p). Font name is \"%s\"\n", current->next, current, NONULL(current->next->name))); @@ -197,11 +234,37 @@ font_cache_del(const void *info) { D_FONT((" -> Reference count is %d. Returning.\n", font_cache->ref_cnt)); } return; +#if UNUSED_BLOCK } else if ((current->next->type == FONT_TYPE_TTF) && (0)) { } else if ((current->next->type == FONT_TYPE_FNLIB) && (0)) { +#endif } } } + /* If we get here, there was no match. No big deal. */ +} + +void +font_cache_clear(void) +{ + cachefont_t *current, *tmp; + + D_FONT(("Clearing the font cache.\n")); + for (current = font_cache; current; ) { + D_FONT((" -> Deleting \"%s\" from cache.\n", current->name)); + tmp = current; + current = current->next; + if (tmp->type == FONT_TYPE_X) { + XFreeFont(Xdisplay, (XFontStruct *) tmp->fontinfo.xfontinfo); + FREE(tmp->name); + FREE(tmp); +#if UNUSED_BLOCK + } else if (current->next->type == FONT_TYPE_TTF) { + } else if (current->next->type == FONT_TYPE_FNLIB) { +#endif + } + } + font_cache = cur_font = NULL; } static cachefont_t * @@ -213,6 +276,7 @@ font_cache_find(const char *name, unsigned char type) { D_FONT(("font_cache_find(%s, %d) called.\n", NONULL(name), type)); + /* Find a matching name/type in the cache. Just a search; no reference counting happens here. */ for (current = font_cache; current; current = current->next) { D_FONT((" -> Checking current (%8p), type == %d, name == %s\n", current, current->type, NONULL(current->name))); if ((current->type == type) && !strcasecmp(current->name, name)) { @@ -233,6 +297,7 @@ font_cache_find_info(const char *name, unsigned char type) { D_FONT(("font_cache_find_info(%s, %d) called.\n", NONULL(name), type)); + /* This is also a simple search, but it returns the fontinfo rather than the cache entry. */ for (current = font_cache; current; current = current->next) { D_FONT((" -> Checking current (%8p), type == %d, name == %s\n", current, current->type, NONULL(current->name))); if ((current->type == type) && !strcasecmp(current->name, name)) { @@ -249,6 +314,7 @@ font_cache_find_info(const char *name, unsigned char type) { return (NULL); } +/* load_font() is the function that should be used to allocate fonts. */ void * load_font(const char *name, const char *fallback, unsigned char type) { @@ -258,9 +324,12 @@ load_font(const char *name, const char *fallback, unsigned char type) D_FONT(("load_font(%s, %s, %d) called.\n", NONULL(name), NONULL(fallback), type)); + /* Default type is X font. */ if (type == 0) { type = FONT_TYPE_X; } + + /* Specify some sane fallbacks */ if (name == NULL) { if (fallback) { name = fallback; @@ -278,6 +347,8 @@ load_font(const char *name, const char *fallback, unsigned char type) } D_FONT((" -> Using name == \"%s\" and fallback == \"%s\"\n", name, fallback)); + /* Look for the font name in the cache. If it's there, add one to the + reference count and return the existing fontinfo pointer to the caller. */ if ((font = font_cache_find(name, type)) != NULL) { font_cache_add_ref(font); D_FONT((" -> Font found in cache. Incrementing reference count to %d and returning existing data.\n", font->ref_cnt)); @@ -288,6 +359,8 @@ load_font(const char *name, const char *fallback, unsigned char type) default: return (NULL); break; } } + + /* No match in the cache, so we'll have to add it. */ if (type == FONT_TYPE_X) { if ((xfont = XLoadQueryFont(Xdisplay, name)) == NULL) { print_error("Unable to load font \"%s\". Falling back on \"%s\"\n", name, fallback); @@ -300,23 +373,26 @@ load_font(const char *name, const char *fallback, unsigned char type) font_cache_add(name, type, (void *) xfont); } return ((void *) xfont); +#if UNUSED_BLOCK } else if (type == FONT_TYPE_TTF) { return (NULL); } else if (type == FONT_TYPE_FNLIB) { return (NULL); +#endif } ASSERT_NOTREACHED_RVAL(NULL); } +/* free_font() is the external function for deallocating fonts. */ void free_font(const void *info) { - ASSERT(info != NULL); - font_cache_del(info); } +/* change_font() handles the font changing escape sequences. It's also called to + initialize the terminal fonts (loading and setting up size hints/info).*/ void change_font(int init, const char *fontname) { @@ -340,12 +416,13 @@ change_font(int init, const char *fontname) ASSERT(fontname != NULL); switch (*fontname) { + /* Empty font name. Reset to default. */ case '\0': font_idx = def_font_idx; fontname = NULL; break; - /* special (internal) prefix for font commands */ + /* A font escape sequence. See which one it is. */ case FONT_CMD: idx = atoi(++fontname); switch (*fontname) { @@ -359,15 +436,18 @@ change_font(int init, const char *fontname) default: if (*fontname != '\0' && !isdigit(*fontname)) - return; + return; /* It's not a number. Punt. */ + /* Set current font to font N */ BOUND(idx, 0, (font_cnt - 1)); font_idx = idx; break; } + /* NULL out the fontname so we don't try to load it */ fontname = NULL; break; default: + /* Change to the named font. See if we already have it, and if so, just set the index. */ for (idx = 0; idx < font_cnt; idx++) { if (!strcasecmp(etfonts[idx], fontname)) { font_idx = idx; @@ -377,31 +457,38 @@ change_font(int init, const char *fontname) } break; } + + /* If we get here with a non-NULL fontname, we have to load a new font. Rats. */ if (fontname != NULL) { eterm_font_add(&etfonts, fontname, font_idx); } else if (font_idx == old_idx) { + /* Sigh. What a waste of time, changing to the same font. */ D_FONT((" -> Change to the same font index (%d) we had before? I don't think so.\n", font_idx)); return; } } D_FONT((" -> Changing to font index %u (\"%s\")\n", (unsigned int) font_idx, NONULL(etfonts[font_idx]))); if (TermWin.font) { + /* If we have a terminal font, but it's not our new current font, free it and load the new one. */ if (font_cache_find_info(etfonts[font_idx], FONT_TYPE_X) != TermWin.font) { free_font(TermWin.font); TermWin.font = load_font(etfonts[font_idx], "fixed", FONT_TYPE_X); } } else { + /* Load the new font. */ TermWin.font = load_font(etfonts[font_idx], "fixed", FONT_TYPE_X); } #ifndef NO_BOLDFONT if (init && rs_boldFont != NULL) { + /* If we're initializing, load the bold font too. */ boldFont = load_font(rs_boldFont, "-misc-fixed-bold-r-semicondensed--13-120-75-75-c-60-iso8859-1", FONT_TYPE_X); } #endif #ifdef MULTI_CHARSET if (TermWin.mfont) { + /* Ditto the above, but for the multi-byte fonts. */ if (font_cache_find_info(etmfonts[font_idx], FONT_TYPE_X) != TermWin.mfont) { free_font(TermWin.mfont); TermWin.mfont = load_font(etmfonts[font_idx], "k14", FONT_TYPE_X); @@ -410,6 +497,7 @@ change_font(int init, const char *fontname) TermWin.mfont = load_font(etmfonts[font_idx], "k14", FONT_TYPE_X); } # ifdef USE_XIM + /* Changing fonts requires updating the FontSet */ if (xim_input_context) { if (TermWin.fontset) { XFreeFontSet(Xdisplay, TermWin.fontset); @@ -421,9 +509,11 @@ change_font(int init, const char *fontname) #endif /* MULTI_CHARSET */ if (!init) { + /* Unless we're initializing, set the font ID in the GC to our new font. */ XSetFont(Xdisplay, TermWin.gc, TermWin.font->fid); } + /* Check the font dimensions to update our TermWin info */ fw = TermWin.font->min_bounds.width; #ifdef MULTI_CHARSET fh = (MAX((encoding_method == LATIN1 ? 0 : TermWin.mfont->ascent), TermWin.font->ascent) @@ -440,6 +530,7 @@ change_font(int init, const char *fontname) else TermWin.fprop = 1; /* Proportional font */ + /* For proportional fonts with large size variations, do some math-fu to try and help the appearance */ if (TermWin.fprop && TermWin.font->per_char && (TermWin.font->max_bounds.width - TermWin.font->min_bounds.width >= 3)) { int cw, n = 0, sum = 0, sumsq = 0, min_w, max_w; unsigned int i; @@ -469,16 +560,16 @@ change_font(int init, const char *fontname) LOWER_BOUND(fw, TermWin.font->max_bounds.width); } - /* not the first time thru and sizes haven't changed */ + /* If the sizes haven't changed, we don't have to update the hints */ if (fw == TermWin.fwidth && fh == TermWin.fheight) return; TermWin.fwidth = fw; TermWin.fheight = fh; - /* check that size of boldFont is okay */ + /* Check the bold font size and make sure it matches the normal font */ #ifndef NO_BOLDFONT - TermWin.boldFont = NULL; + TermWin.boldFont = NULL; /* FIXME: Memory leak? Not that anyone uses bold fonts.... */ if (boldFont != NULL) { fw = boldFont->min_bounds.width; @@ -502,6 +593,7 @@ change_font(int init, const char *fontname) TermWin.height = TermWin.nrow * TermWin.fheight; D_FONT((" -> New font width/height = %ldx%ld, making the terminal size %ldx%ld\n", TermWin.fwidth, TermWin.fheight, TermWin.width, TermWin.height)); + /* If we're initializing, *we* do the size hints. If not, resize the parent window. */ if (init) { szHint.width_inc = TermWin.fwidth; szHint.height_inc = TermWin.fheight; diff --git a/src/font.h b/src/font.h index b96956c..94c3816 100644 --- a/src/font.h +++ b/src/font.h @@ -46,6 +46,7 @@ #define SHADOW_BOTTOM_LEFT 2 #define SHADOW_BOTTOM_RIGHT 3 +/* The macros are used to advance to the next/previous font as with Ctrl-> and Ctrl-< */ #define NEXT_FONT(i) do { if (font_idx + ((i)?(i):1) >= font_cnt) {font_idx = font_cnt - 1;} else {font_idx += ((i)?(i):1);} \ while (!etfonts[font_idx]) {if (font_idx == font_cnt) {font_idx--; break;} font_idx++;} } while (0) #define PREV_FONT(i) do { if (font_idx - ((i)?(i):1) < 0) {font_idx = 0;} else {font_idx -= ((i)?(i):1);} \ @@ -55,10 +56,11 @@ /************ Structures ************/ typedef struct cachefont_struct { - char *name; - unsigned char type; - unsigned char ref_cnt; + char *name; /* Font name in canonical format */ + unsigned char type; /* Font type (FONT_TYPE_* from above */ + unsigned char ref_cnt; /* Reference count */ union { + /* This union will eventually have members for TTF/Fnlib fonts */ XFontStruct *xfontinfo; } fontinfo; struct cachefont_struct *next; @@ -86,6 +88,8 @@ _XFUNCPROTOBEGIN extern void eterm_font_add(char ***plist, const char *fontname, unsigned char idx); extern void eterm_font_delete(char **flist, unsigned char idx); +extern void eterm_font_list_clear(void); +extern void font_cache_clear(void); extern void *load_font(const char *, const char *, unsigned char); extern void free_font(const void *); extern void change_font(int, const char *); diff --git a/src/menus.c b/src/menus.c index ba182c6..dd1d2cf 100644 --- a/src/menus.c +++ b/src/menus.c @@ -156,7 +156,7 @@ menu_event_init_dispatcher(void) } unsigned char -menu_handle_enter_notify(event_t * ev) +menu_handle_enter_notify(event_t *ev) { register menu_t *menu; @@ -181,7 +181,7 @@ menu_handle_enter_notify(event_t * ev) } unsigned char -menu_handle_leave_notify(event_t * ev) +menu_handle_leave_notify(event_t *ev) { D_EVENTS(("menu_handle_leave_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -195,7 +195,7 @@ menu_handle_leave_notify(event_t * ev) } unsigned char -menu_handle_focus_in(event_t * ev) +menu_handle_focus_in(event_t *ev) { D_EVENTS(("menu_handle_focus_in(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -206,7 +206,7 @@ menu_handle_focus_in(event_t * ev) } unsigned char -menu_handle_focus_out(event_t * ev) +menu_handle_focus_out(event_t *ev) { D_EVENTS(("menu_handle_focus_out(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -218,7 +218,7 @@ menu_handle_focus_out(event_t * ev) #if 0 unsigned char -menu_handle_expose(event_t * ev) +menu_handle_expose(event_t *ev) { XEvent unused_xevent; @@ -234,7 +234,7 @@ menu_handle_expose(event_t * ev) #endif unsigned char -menu_handle_button_press(event_t * ev) +menu_handle_button_press(event_t *ev) { D_EVENTS(("menu_handle_button_press(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -270,7 +270,7 @@ menu_handle_button_press(event_t * ev) } unsigned char -menu_handle_button_release(event_t * ev) +menu_handle_button_release(event_t *ev) { menuitem_t *item; @@ -333,7 +333,7 @@ menu_handle_button_release(event_t * ev) } unsigned char -menu_handle_motion_notify(event_t * ev) +menu_handle_motion_notify(event_t *ev) { register menuitem_t *item = NULL; @@ -392,7 +392,7 @@ menu_handle_motion_notify(event_t * ev) } unsigned char -menu_dispatch_event(event_t * ev) +menu_dispatch_event(event_t *ev) { if (menu_event_data.handlers[ev->type] != NULL) { return ((menu_event_data.handlers[ev->type]) (ev)); @@ -401,9 +401,8 @@ menu_dispatch_event(event_t * ev) } menulist_t * -menulist_add_menu(menulist_t * list, menu_t * menu) +menulist_add_menu(menulist_t *list, menu_t *menu) { - ASSERT_RVAL(menu != NULL, list); if (list) { @@ -418,10 +417,25 @@ menulist_add_menu(menulist_t * list, menu_t * menu) return list; } +void +menulist_clear(menulist_t *list) +{ + unsigned long i; + + ASSERT(list != NULL); + + for (i = 0; i < list->nummenus; i++) { + menu_delete(list->menus[i]); + } + FREE(list->menus); + LIBMEJ_X_FREE_GC(topShadowGC); + LIBMEJ_X_FREE_GC(botShadowGC); + FREE(list); +} + menu_t * menu_create(char *title) { - menu_t *menu; static Cursor cursor; static long mask; @@ -456,6 +470,43 @@ menu_create(char *title) return menu; } +void +menu_delete(menu_t *menu) +{ + unsigned short i; + + ASSERT(menu != NULL); + + for (i = 0; i < menu->numitems; i++) { + menuitem_delete(menu->items[i]); + } + FREE(menu->items); + if (menu->title) { + FREE(menu->title); + } + if (menu->bg) { + LIBMEJ_X_FREE_PIXMAP(menu->bg); + } + if (menu->gc) { + LIBMEJ_X_FREE_GC(menu->gc); + } +#ifdef MULTI_CHARSET + if (menu->fontset) { + XFreeFontSet(Xdisplay, menu->fontset); + } +#endif + if (menu->font) { + free_font(menu->font); + } + if (menu->win) { + XDestroyWindow(Xdisplay, menu->win); + } + if (menu->swin) { + XDestroyWindow(Xdisplay, menu->swin); + } + FREE(menu); +} + unsigned char menu_set_title(menu_t *menu, const char *title) { @@ -469,9 +520,8 @@ menu_set_title(menu_t *menu, const char *title) } unsigned char -menu_set_font(menu_t * menu, const char *fontname) +menu_set_font(menu_t *menu, const char *fontname) { - XFontStruct *font; XGCValues gcvalue; @@ -494,9 +544,8 @@ menu_set_font(menu_t * menu, const char *fontname) } unsigned char -menu_add_item(menu_t * menu, menuitem_t * item) +menu_add_item(menu_t *menu, menuitem_t *item) { - ASSERT_RVAL(menu != NULL, 0); ASSERT_RVAL(item != NULL, 0); @@ -515,9 +564,8 @@ menu_add_item(menu_t * menu, menuitem_t * item) /* Return 1 if submenu is a child of menu, 0 if not. */ unsigned char -menu_is_child(menu_t * menu, menu_t * submenu) +menu_is_child(menu_t *menu, menu_t *submenu) { - register unsigned char i; register menuitem_t *item; @@ -538,9 +586,8 @@ menu_is_child(menu_t * menu, menu_t * submenu) } menu_t * -find_menu_by_title(menulist_t * list, char *title) +find_menu_by_title(menulist_t *list, char *title) { - register unsigned char i; REQUIRE_RVAL(list != NULL, NULL); @@ -554,9 +601,8 @@ find_menu_by_title(menulist_t * list, char *title) } menu_t * -find_menu_by_window(menulist_t * list, Window win) +find_menu_by_window(menulist_t *list, Window win) { - register unsigned char i; REQUIRE_RVAL(list != NULL, NULL); @@ -570,9 +616,8 @@ find_menu_by_window(menulist_t * list, Window win) } menuitem_t * -find_item_by_coords(menu_t * menu, int x, int y) +find_item_by_coords(menu_t *menu, int x, int y) { - register unsigned char i; register menuitem_t *item; @@ -588,9 +633,8 @@ find_item_by_coords(menu_t * menu, int x, int y) } unsigned short -find_item_in_menu(menu_t * menu, menuitem_t * item) +find_item_in_menu(menu_t *menu, menuitem_t *item) { - register unsigned char i; ASSERT_RVAL(menu != NULL, (unsigned short) -1); @@ -646,7 +690,6 @@ menuitem_change_current(menuitem_t *item) menuitem_t * menuitem_create(char *text) { - menuitem_t *menuitem; menuitem = (menuitem_t *) MALLOC(sizeof(menuitem_t)); @@ -659,8 +702,28 @@ menuitem_create(char *text) return menuitem; } +void +menuitem_delete(menuitem_t *item) +{ + ASSERT(item != NULL); + + if (item->icon) { + free_simage(item->icon); + } + if (item->type == MENUITEM_STRING || item->type == MENUITEM_ECHO) { + FREE(item->action.string); + } + if (item->text) { + FREE(item->text); + } + if (item->rtext) { + FREE(item->rtext); + } + FREE(item); +} + unsigned char -menuitem_set_text(menuitem_t * item, const char *text) +menuitem_set_text(menuitem_t *item, const char *text) { ASSERT_RVAL(item != NULL, 0); REQUIRE_RVAL(text != NULL, 0); @@ -674,9 +737,8 @@ menuitem_set_text(menuitem_t * item, const char *text) } unsigned char -menuitem_set_icon(menuitem_t * item, simage_t * icon) +menuitem_set_icon(menuitem_t *item, simage_t *icon) { - ASSERT_RVAL(item != NULL, 0); ASSERT_RVAL(icon != NULL, 0); @@ -685,9 +747,8 @@ menuitem_set_icon(menuitem_t * item, simage_t * icon) } unsigned char -menuitem_set_action(menuitem_t * item, unsigned char type, char *action) +menuitem_set_action(menuitem_t *item, unsigned char type, char *action) { - ASSERT_RVAL(item != NULL, 0); item->type = type; @@ -708,9 +769,8 @@ menuitem_set_action(menuitem_t * item, unsigned char type, char *action) } unsigned char -menuitem_set_rtext(menuitem_t * item, char *rtext) +menuitem_set_rtext(menuitem_t *item, char *rtext) { - ASSERT_RVAL(item != NULL, 0); ASSERT_RVAL(rtext != NULL, 0); @@ -720,9 +780,8 @@ menuitem_set_rtext(menuitem_t * item, char *rtext) } void -menu_reset(menu_t * menu) +menu_reset(menu_t *menu) { - ASSERT(menu != NULL); D_MENU(("menu_reset(menu %8p \"%s\"), window 0x%08x\n", menu, menu->title, menu->win)); @@ -736,7 +795,7 @@ menu_reset(menu_t * menu) } void -menu_reset_all(menulist_t * list) +menu_reset_all(menulist_t *list) { register unsigned short i; @@ -756,9 +815,8 @@ menu_reset_all(menulist_t * list) } void -menu_reset_tree(menu_t * menu) +menu_reset_tree(menu_t *menu) { - register unsigned short i; register menuitem_t *item; @@ -778,9 +836,8 @@ menu_reset_tree(menu_t * menu) } void -menu_reset_submenus(menu_t * menu) +menu_reset_submenus(menu_t *menu) { - register unsigned short i; register menuitem_t *item; @@ -796,7 +853,7 @@ menu_reset_submenus(menu_t * menu) } void -menuitem_select(menu_t * menu) +menuitem_select(menu_t *menu) { static Pixel top = 0, bottom = 0; menuitem_t *item; @@ -822,9 +879,6 @@ menuitem_select(menu_t * menu) draw_shadow_from_colors(menu->swin, top, bottom, 0, 0, item->w - MENU_VGAP, item->h, 2); draw_arrow_from_colors(menu->swin, top, bottom, item->w - 3 * MENU_HGAP, (item->h - MENU_VGAP) / 2, MENU_VGAP, 2, DRAW_ARROW_RIGHT); } -#if 0 - paste_simage(images[image_submenu].selected, image_submenu, menu->swin, 0, 0, item->w - MENU_VGAP, item->h); -#endif } else { if (image_mode_is(image_menu, MODE_MASK)) { render_simage(images[image_menu].selected, menu->swin, item->w - MENU_VGAP, item->h, image_menu, 0); @@ -844,7 +898,7 @@ menuitem_select(menu_t * menu) } void -menuitem_deselect(menu_t * menu) +menuitem_deselect(menu_t *menu) { menuitem_t *item; @@ -858,7 +912,7 @@ menuitem_deselect(menu_t * menu) } void -menu_display_submenu(menu_t * menu, menuitem_t * item) +menu_display_submenu(menu_t *menu, menuitem_t *item) { menu_t *submenu; @@ -893,9 +947,8 @@ menu_move(menu_t *menu, unsigned short x, unsigned short y) { } void -menu_draw(menu_t * menu) +menu_draw(menu_t *menu) { - register unsigned short i, len; unsigned long width, height; #if 0 @@ -1070,9 +1123,8 @@ menu_draw(menu_t * menu) } void -menu_display(int x, int y, menu_t * menu) +menu_display(int x, int y, menu_t *menu) { - ASSERT(menu != NULL); menu->state |= (MENU_STATE_IS_CURRENT); @@ -1091,9 +1143,8 @@ menu_display(int x, int y, menu_t * menu) } void -menu_action(menuitem_t * item) +menu_action(menuitem_t *item) { - ASSERT(item != NULL); D_MENU(("menu_action() called to invoke %s\n", item->text)); @@ -1117,9 +1168,8 @@ menu_action(menuitem_t * item) } void -menu_invoke(int x, int y, Window win, menu_t * menu, Time timestamp) +menu_invoke(int x, int y, Window win, menu_t *menu, Time timestamp) { - int root_x, root_y; Window unused; @@ -1138,7 +1188,6 @@ menu_invoke(int x, int y, Window win, menu_t * menu, Time timestamp) void menu_invoke_by_title(int x, int y, Window win, char *title, Time timestamp) { - menu_t *menu; REQUIRE(title != NULL); diff --git a/src/menus.h b/src/menus.h index 5ee557c..c606715 100644 --- a/src/menus.h +++ b/src/menus.h @@ -106,7 +106,9 @@ extern unsigned char menu_handle_button_release(event_t *); extern unsigned char menu_handle_motion_notify(event_t *); extern unsigned char menu_dispatch_event(event_t *); extern menulist_t *menulist_add_menu(menulist_t *, menu_t *); +extern void menulist_clear(menulist_t *); extern menu_t *menu_create(char *); +extern void menu_delete(menu_t *); extern unsigned char menu_set_title(menu_t *, const char *); extern unsigned char menu_set_font(menu_t *, const char *); extern unsigned char menu_add_item(menu_t *, menuitem_t *); @@ -117,6 +119,7 @@ extern menuitem_t *find_item_by_coords(menu_t *, int, int); extern unsigned short find_item_in_menu(menu_t *, menuitem_t *); extern void menuitem_change_current(menuitem_t *); extern menuitem_t *menuitem_create(char *); +extern void menuitem_delete(menuitem_t *); extern unsigned char menuitem_set_text(menuitem_t *, const char *); extern unsigned char menuitem_set_icon(menuitem_t *, simage_t *); extern unsigned char menuitem_set_action(menuitem_t *, unsigned char, char *); diff --git a/src/pixmap.c b/src/pixmap.c index 6a5e4ef..edb6bea 100644 --- a/src/pixmap.c +++ b/src/pixmap.c @@ -344,7 +344,7 @@ create_simage(void) } void -reset_simage(simage_t * simg, unsigned long mask) +reset_simage(simage_t *simg, unsigned long mask) { ASSERT(simg != NULL); @@ -818,7 +818,7 @@ copy_buffer_pixmap(unsigned char mode, unsigned long fill, unsigned short width, } void -render_simage(simage_t * simg, Window win, unsigned short width, unsigned short height, unsigned char which, renderop_t renderop) +render_simage(simage_t *simg, Window win, unsigned short width, unsigned short height, unsigned char which, renderop_t renderop) { XGCValues gcvalue; diff --git a/src/screen.c b/src/screen.c index d352993..e96052b 100644 --- a/src/screen.c +++ b/src/screen.c @@ -102,7 +102,7 @@ encoding_t encoding_method = LATIN1; /* Fill part/all of a drawn line with blanks. */ inline void blank_line(text_t *, rend_t *, int, rend_t); inline void -blank_line(text_t * et, rend_t * er, int width, rend_t efs) +blank_line(text_t *et, rend_t *er, int width, rend_t efs) { /* int i = width; */ register unsigned int i = width; @@ -2713,7 +2713,7 @@ selection_click(int clicks, int x, int y) #endif void -selection_delimit_word(int col, int row, row_col_t * beg, row_col_t * end) +selection_delimit_word(int col, int row, row_col_t *beg, row_col_t *end) { int beg_col, beg_row, end_col, end_row, last_col; int row_offset, w1; diff --git a/src/scrollbar.c b/src/scrollbar.c index 3336776..e72ab67 100644 --- a/src/scrollbar.c +++ b/src/scrollbar.c @@ -94,7 +94,7 @@ scrollbar_event_init_dispatcher(void) } unsigned char -sb_handle_enter_notify(event_t * ev) +sb_handle_enter_notify(event_t *ev) { D_EVENTS(("sb_handle_enter_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -114,7 +114,7 @@ sb_handle_enter_notify(event_t * ev) } unsigned char -sb_handle_leave_notify(event_t * ev) +sb_handle_leave_notify(event_t *ev) { D_EVENTS(("sb_handle_leave_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -134,7 +134,7 @@ sb_handle_leave_notify(event_t * ev) } unsigned char -sb_handle_focus_in(event_t * ev) +sb_handle_focus_in(event_t *ev) { D_EVENTS(("sb_handle_focus_in(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -145,7 +145,7 @@ sb_handle_focus_in(event_t * ev) } unsigned char -sb_handle_focus_out(event_t * ev) +sb_handle_focus_out(event_t *ev) { D_EVENTS(("sb_handle_focus_out(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -156,7 +156,7 @@ sb_handle_focus_out(event_t * ev) } unsigned char -sb_handle_expose(event_t * ev) +sb_handle_expose(event_t *ev) { XEvent unused_xevent; @@ -181,7 +181,7 @@ sb_handle_expose(event_t * ev) } unsigned char -sb_handle_button_press(event_t * ev) +sb_handle_button_press(event_t *ev) { D_EVENTS(("sb_handle_button_press(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -282,7 +282,7 @@ sb_handle_button_press(event_t * ev) } unsigned char -sb_handle_button_release(event_t * ev) +sb_handle_button_release(event_t *ev) { Window root, child; @@ -321,7 +321,7 @@ sb_handle_button_release(event_t * ev) } unsigned char -sb_handle_motion_notify(event_t * ev) +sb_handle_motion_notify(event_t *ev) { D_EVENTS(("sb_handle_motion_notify(ev [%8p] on window 0x%08x)\n", ev, ev->xany.window)); @@ -349,7 +349,7 @@ sb_handle_motion_notify(event_t * ev) } unsigned char -scrollbar_dispatch_event(event_t * ev) +scrollbar_dispatch_event(event_t *ev) { if (scrollbar_event_data.handlers[ev->type] != NULL) { return ((scrollbar_event_data.handlers[ev->type]) (ev));