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));