28#include <glib/gi18n.h>
36#include "gnc-component-manager.h"
47static QofLogModule log_module = GNC_MOD_GUI;
50static void gnc_tree_view_commodity_finalize (GObject *
object);
51static void gnc_tree_view_commodity_destroy (GtkWidget *widget);
55 GncTreeView gnc_tree_view;
63G_DEFINE_TYPE(GncTreeViewCommodity, gnc_tree_view_commodity, GNC_TYPE_TREE_VIEW)
66gnc_tree_view_commodity_class_init (GncTreeViewCommodityClass *klass)
68 GObjectClass *o_class;
69 GtkWidgetClass *widget_class;
71 o_class = G_OBJECT_CLASS (klass);
72 widget_class = GTK_WIDGET_CLASS (klass);
75 o_class->finalize = gnc_tree_view_commodity_finalize;
78 widget_class->destroy = gnc_tree_view_commodity_destroy;
82gnc_tree_view_commodity_init (GncTreeViewCommodity *view)
87gnc_tree_view_commodity_finalize (GObject *
object)
89 g_return_if_fail (
object != NULL);
90 g_return_if_fail (GNC_IS_TREE_VIEW_COMMODITY (
object));
92 ENTER(
"view %p",
object);
93 G_OBJECT_CLASS (gnc_tree_view_commodity_parent_class)->finalize (
object);
98gnc_tree_view_commodity_destroy (GtkWidget *widget)
100 g_return_if_fail (widget != NULL);
101 g_return_if_fail (GNC_IS_TREE_VIEW_COMMODITY (widget));
103 ENTER(
"view %p", widget);
105 GTK_WIDGET_CLASS (gnc_tree_view_commodity_parent_class)->destroy (widget);
115get_commodities_w_iters (GtkTreeModel *f_model,
116 GtkTreeIter *f_iter_a,
117 GtkTreeIter *f_iter_b,
118 GtkTreeModel **model_p,
121 gnc_commodity **comm_a,
122 gnc_commodity **comm_b)
124 GncTreeModelCommodity *model;
125 GtkTreeModel *tree_model;
127 tree_model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
128 model = GNC_TREE_MODEL_COMMODITY(tree_model);
130 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
134 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
147 *model_p = tree_model;
152get_commodities (GtkTreeModel *f_model,
153 GtkTreeIter *f_iter_a,
154 GtkTreeIter *f_iter_b,
155 GtkTreeModel **model_p,
156 gnc_commodity **comm_a,
157 gnc_commodity **comm_b)
159 GtkTreeIter iter_a, iter_b;
161 return get_commodities_w_iters(f_model, f_iter_a, f_iter_b, model_p,
162 &iter_a, &iter_b, comm_a, comm_b);
166sort_namespace (GtkTreeModel *f_model,
167 GtkTreeIter *f_iter_a,
168 GtkTreeIter *f_iter_b)
170 GncTreeModelCommodity *model;
171 GtkTreeModel *tree_model;
172 GtkTreeIter iter_a, iter_b;
173 gnc_commodity_namespace *ns_a, *ns_b;
175 tree_model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
176 model = GNC_TREE_MODEL_COMMODITY(tree_model);
178 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
181 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
192default_sort (gnc_commodity *comm_a, gnc_commodity *comm_b)
194 gint fraction_a, fraction_b, result;
198 if (result != 0)
return result;
202 if (result != 0)
return result;
206 if (result != 0)
return result;
210 if (result != 0)
return result;
215 if (fraction_a < fraction_b)
218 if (fraction_b < fraction_a)
225sort_by_commodity_string (GtkTreeModel *f_model,
226 GtkTreeIter *f_iter_a,
227 GtkTreeIter *f_iter_b,
231 GtkTreeIter iter_a, iter_b;
232 gnc_commodity *comm_a, *comm_b;
234 gint column = GPOINTER_TO_INT(user_data);
237 if (!get_commodities_w_iters(f_model, f_iter_a, f_iter_b,
238 &model, &iter_a, &iter_b, &comm_a, &comm_b))
239 return sort_namespace (f_model, f_iter_a, f_iter_b);
242 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter_a, column, &str1, -1);
243 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter_b, column, &str2, -1);
250 return default_sort(comm_a, comm_b);
255sort_by_fraction (GtkTreeModel *f_model,
256 GtkTreeIter *f_iter_a,
257 GtkTreeIter *f_iter_b,
260 gnc_commodity *comm_a, *comm_b;
261 gint fraction_a, fraction_b;
263 if (!get_commodities (f_model, f_iter_a, f_iter_b, NULL, &comm_a, &comm_b))
264 return sort_namespace (f_model, f_iter_a, f_iter_b);
269 if (fraction_a < fraction_b)
272 if (fraction_b < fraction_a)
275 return default_sort(comm_a, comm_b);
279sort_by_quote_flag (GtkTreeModel *f_model,
280 GtkTreeIter *f_iter_a,
281 GtkTreeIter *f_iter_b,
284 gnc_commodity *comm_a, *comm_b;
285 gboolean flag_a, flag_b;
287 if (!get_commodities (f_model, f_iter_a, f_iter_b, NULL, &comm_a, &comm_b))
288 return sort_namespace (f_model, f_iter_a, f_iter_b);
295 else if (flag_a > flag_b)
297 return default_sort(comm_a, comm_b);
312 const gchar *first_property_name,
316 GtkTreeModel *model, *f_model, *s_model;
317 GtkTreeViewColumn *col;
318 gnc_commodity_table *ct;
327 f_model = gtk_tree_model_filter_new (model, NULL);
328 g_object_unref(G_OBJECT(model));
329 s_model = gtk_tree_model_sort_new_with_model (f_model);
330 g_object_unref(G_OBJECT(f_model));
333 view = g_object_new (GNC_TYPE_TREE_VIEW_COMMODITY,
334 "name",
"gnc-id-commodity-tree", NULL);
335 gtk_tree_view_set_model (GTK_TREE_VIEW (view), s_model);
336 g_object_unref(G_OBJECT(s_model));
338 DEBUG(
"model ref count is %d", G_OBJECT(model)->ref_count);
339 DEBUG(
"f_model ref count is %d", G_OBJECT(f_model)->ref_count);
340 DEBUG(
"s_model ref count is %d", G_OBJECT(s_model)->ref_count);
343 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
346 view, _(
"Namespace"),
"namespace", NULL,
"NASDAQ",
347 GNC_TREE_MODEL_COMMODITY_COL_NAMESPACE,
348 GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
349 sort_by_commodity_string);
351 view, _(
"Symbol"),
"symbol", NULL,
"ACMEACME",
352 GNC_TREE_MODEL_COMMODITY_COL_MNEMONIC,
353 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
354 sort_by_commodity_string);
355 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
357 view, _(
"Name"),
"name", NULL,
"Acme Corporation, Inc.",
358 GNC_TREE_MODEL_COMMODITY_COL_FULLNAME,
359 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
360 sort_by_commodity_string);
361 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
363 view, _(
"Print Name"),
"printname", NULL,
364 "ACMEACME (Acme Corporation, Inc.)",
365 GNC_TREE_MODEL_COMMODITY_COL_PRINTNAME,
366 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
367 sort_by_commodity_string);
369 view, _(
"Display symbol"),
"user_symbol", NULL,
"ACME",
370 GNC_TREE_MODEL_COMMODITY_COL_USER_SYMBOL,
371 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
372 sort_by_commodity_string);
373 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
375 view, _(
"Unique Name"),
"uniquename", NULL,
376 "NASDAQ::ACMEACME", GNC_TREE_MODEL_COMMODITY_COL_UNIQUE_NAME,
377 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
378 sort_by_commodity_string);
382 view, _(
"ISIN/CUSIP"),
"cusip_code", NULL,
"US1234567890",
383 GNC_TREE_MODEL_COMMODITY_COL_CUSIP,
384 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
385 sort_by_commodity_string);
386 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
388 view, _(
"Fraction"),
"fraction",
"10000",
389 GNC_TREE_MODEL_COMMODITY_COL_FRACTION,
390 GNC_TREE_VIEW_COLUMN_COLOR_NONE,
391 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
393 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
395 view, _(
"Get Quotes"),
396 C_(
"Column letter for 'Get Quotes'",
"Q"),
"quote_flag",
397 GNC_TREE_MODEL_COMMODITY_COL_QUOTE_FLAG,
398 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
402 view, _(
"Source"),
"quote_source", NULL,
"alphavantage",
403 GNC_TREE_MODEL_COMMODITY_COL_QUOTE_SOURCE,
404 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
405 sort_by_commodity_string);
407 view, _(
"Timezone"),
"quote_timezone", NULL,
"America/New_York",
408 GNC_TREE_MODEL_COMMODITY_COL_QUOTE_TZ,
409 GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
410 sort_by_commodity_string);
411 g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
416 va_start (var_args, first_property_name);
417 g_object_set_valist (G_OBJECT(view), first_property_name, var_args);
422 if (!gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(s_model),
425 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_model),
426 GNC_TREE_MODEL_COMMODITY_COL_FULLNAME,
430 gtk_widget_show(GTK_WIDGET(view));
432 return GTK_TREE_VIEW(view);
439#define debug_path(fn, path) { \
440 gchar *path_string = gtk_tree_path_to_string(path); \
441 fn("tree path %s", path_string); \
442 g_free(path_string); \
447gnc_tree_view_commodity_get_iter_from_commodity (GncTreeViewCommodity *view,
448 gnc_commodity *commodity,
451 GtkTreeModel *model, *f_model, *s_model;
452 GtkTreeIter iter, f_iter;
454 g_return_val_if_fail(GNC_IS_TREE_VIEW_COMMODITY(view), FALSE);
455 g_return_val_if_fail(commodity != NULL, FALSE);
456 g_return_val_if_fail(s_iter != NULL, FALSE);
461 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
462 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
463 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
466 LEAVE(
"model_get_iter_from_commodity failed");
471 gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER(f_model),
473 gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(s_model),
486 gnc_tree_view_commodity_ns_filter_func user_ns_fn;
487 gnc_tree_view_commodity_cm_filter_func user_cm_fn;
489 GDestroyNotify user_destroy;
493gnc_tree_view_commodity_filter_destroy (gpointer data)
497 if (fd->user_destroy)
498 fd->user_destroy(fd->user_data);
503gnc_tree_view_commodity_filter_helper (GtkTreeModel *model,
507 gnc_commodity_namespace *name_space;
508 gnc_commodity *commodity;
511 g_return_val_if_fail (GNC_IS_TREE_MODEL_COMMODITY (model), FALSE);
512 g_return_val_if_fail (iter != NULL, FALSE);
519 return fd->user_ns_fn(name_space, fd->user_data);
529 return fd->user_cm_fn(commodity, fd->user_data);
544 gnc_tree_view_commodity_ns_filter_func ns_func,
545 gnc_tree_view_commodity_cm_filter_func cm_func,
547 GDestroyNotify destroy)
549 GtkTreeModel *f_model, *s_model;
552 g_return_if_fail(GNC_IS_TREE_VIEW_COMMODITY(view));
553 g_return_if_fail((ns_func != NULL) || (cm_func != NULL));
555 ENTER(
"view %p, ns func %p, cm func %p, data %p, destroy %p",
556 view, ns_func, cm_func, data, destroy);
559 fd->user_ns_fn = ns_func;
560 fd->user_cm_fn = cm_func;
561 fd->user_data = data;
562 fd->user_destroy = destroy;
564 s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
565 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
568 g_object_ref (G_OBJECT(s_model));
569 gtk_tree_view_set_model (GTK_TREE_VIEW(view), NULL);
571 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (f_model),
572 gnc_tree_view_commodity_filter_helper,
574 gnc_tree_view_commodity_filter_destroy);
578 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
581 gtk_tree_view_set_model (GTK_TREE_VIEW(view), s_model);
582 g_object_unref (G_OBJECT(s_model));
593 GtkTreeModel *f_model, *s_model;
595 g_return_if_fail(GNC_IS_TREE_VIEW_COMMODITY(view));
597 ENTER(
"view %p", view);
598 s_model = gtk_tree_view_get_model (GTK_TREE_VIEW(view));
599 f_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (s_model));
600 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (f_model));
616 GtkTreeSelection *selection;
617 GtkTreeModel *model, *f_model, *s_model;
618 GtkTreeIter iter, f_iter, s_iter;
619 gnc_commodity *commodity;
621 g_return_val_if_fail (GNC_IS_TREE_VIEW_COMMODITY (view), NULL);
623 ENTER(
"view %p", view);
625 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
626 if (!gtk_tree_selection_get_selected (selection, &s_model, &s_iter))
628 LEAVE(
"no commodity, get_selected failed");
632 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
635 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
636 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model),
639 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
642 LEAVE(
"commodity %p (%s)", commodity,
651gnc_commodity_namespace *
654 GtkTreeSelection *selection;
655 GtkTreeModel *model, *f_model, *s_model;
656 GtkTreeIter iter, f_iter, s_iter;
657 gnc_commodity_namespace *ns;
659 g_return_val_if_fail (GNC_IS_TREE_VIEW_COMMODITY(view), NULL);
661 ENTER(
"view %p", view);
663 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
664 if (!gtk_tree_selection_get_selected (selection, &s_model, &s_iter))
666 LEAVE(
"no namespace, get_selected failed");
670 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
673 f_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT(s_model));
674 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER(f_model),
677 model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER(f_model));
682 LEAVE(
"namespace %p (%s)", ns,
693 GtkTreeSelection *selection;
694 GtkTreeModel *model, *f_model, *s_model;
695 GtkTreePath *tree_path;
696 GtkTreePath *f_tree_path;
697 GtkTreePath *s_tree_path;
699 g_return_if_fail (GNC_IS_TREE_VIEW_COMMODITY(view));
704 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
706 s_model = gtk_tree_view_get_model (GTK_TREE_VIEW(view));
707 f_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (s_model));
708 model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (f_model));
714 f_tree_path = gtk_tree_model_filter_convert_child_path_to_path
715 (GTK_TREE_MODEL_FILTER (f_model), tree_path);
717 s_tree_path = gtk_tree_model_sort_convert_child_path_to_path
718 (GTK_TREE_MODEL_SORT (s_model), f_tree_path);
720 gtk_tree_view_expand_to_path (GTK_TREE_VIEW(view), s_tree_path);
721 gtk_tree_selection_select_path (selection, s_tree_path);
722 gtk_tree_path_free (tree_path);
723 gtk_tree_path_free (f_tree_path);
724 gtk_tree_path_free (s_tree_path);
735get_selected_commodities_helper (GtkTreeModel *s_model,
740 GList **return_list = data;
741 GtkTreeModel *model, *f_model;
742 GtkTreeIter iter, f_iter;
743 gnc_commodity *commodity;
745 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (s_model),
748 f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model));
749 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (f_model),
752 model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model));
755 *return_list = g_list_append(*return_list, commodity);
Commodity handling public routines.
All type declarations for the whole Gnucash engine.
Gnome specific utility functions.
GtkTreeModel implementation for gnucash commodities.
GtkTreeView implementation for gnucash commodity tree.
common utilities for manipulating a GtkTreeView within gnucash
utility functions for the GnuCash UI
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Retrieve the full name for the specified commodity.
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
Retrieve the namespace for the specified commodity.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
const char * gnc_commodity_get_cusip(const gnc_commodity *cm)
Retrieve the 'exchange code' for the specified commodity.
const char * gnc_commodity_namespace_get_name(const gnc_commodity_namespace *ns)
Return the textual name of a namespace data structure.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
gboolean gnc_commodity_get_quote_flag(const gnc_commodity *cm)
Retrieve the automatic price quote flag for the specified commodity.
const char * gnc_commodity_namespace_get_gui_name(const gnc_commodity_namespace *ns)
Return the textual name of a namespace data structure in a form suitable to present to the user.
void gnc_tree_view_configure_columns(GncTreeView *view)
Make all the correct columns visible, respecting their default visibility setting,...
GtkTreeViewColumn * gnc_tree_view_add_text_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *icon_name, const gchar *sizing_text, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
This function adds a new text column to a GncTreeView base view.
GtkTreeViewColumn * gnc_tree_view_add_toggle_column(GncTreeView *view, const gchar *column_title, const gchar *column_short_title, const gchar *pref_name, gint model_data_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn, renderer_toggled toggle_edited_cb)
This function adds a new toggle column to a GncTreeView base view.
GtkTreeViewColumn * gnc_tree_view_add_numeric_column(GncTreeView *view, const gchar *column_title, const gchar *pref_name, const gchar *sizing_text, gint model_data_column, gint model_color_column, gint model_visibility_column, GtkTreeIterCompareFunc column_sort_fn)
This function adds a new numeric column to a GncTreeView base view.
gnc_commodity * gnc_tree_model_commodity_get_commodity(GncTreeModelCommodity *model, GtkTreeIter *iter)
Convert a model/iter pair to a gnucash commodity.
gboolean gnc_tree_model_commodity_iter_is_namespace(GncTreeModelCommodity *model, GtkTreeIter *iter)
Determine whether or not the specified GtkTreeIter points to a commodity namespace.
gboolean gnc_tree_model_commodity_get_iter_from_commodity(GncTreeModelCommodity *model, gnc_commodity *commodity, GtkTreeIter *iter)
Convert a commodity pointer into a GtkTreeIter.
gnc_commodity * gnc_tree_view_commodity_get_selected_commodity(GncTreeViewCommodity *view)
This function returns the commodity associated with the selected item in the commodity tree view.
GtkTreeModel * gnc_tree_model_commodity_new(QofBook *book, gnc_commodity_table *ct)
Create a new GtkTreeModel for manipulating gnucash commodities.
void gnc_tree_view_commodity_refilter(GncTreeViewCommodity *view)
This function forces the commodity tree filter to be evaluated.
void gnc_tree_view_commodity_set_filter(GncTreeViewCommodity *view, gnc_tree_view_commodity_ns_filter_func ns_func, gnc_tree_view_commodity_cm_filter_func cm_func, gpointer data, GDestroyNotify destroy)
This function attaches a filter function to the given commodity tree.
GtkTreeView * gnc_tree_view_commodity_new(QofBook *book, const gchar *first_property_name,...)
Create a new commodity tree view.
gboolean gnc_tree_model_commodity_iter_is_commodity(GncTreeModelCommodity *model, GtkTreeIter *iter)
Determine whether or not the specified GtkTreeIter points to a commodity.
gnc_commodity_namespace * gnc_tree_model_commodity_get_namespace(GncTreeModelCommodity *model, GtkTreeIter *iter)
Convert a model/iter pair to a gnucash commodity namespace.
void gnc_tree_view_commodity_select_commodity(GncTreeViewCommodity *view, gnc_commodity *commodity)
Select the commodity in the associated commodity tree view.
gnc_commodity_namespace * gnc_tree_view_commodity_get_selected_namespace(GncTreeViewCommodity *view)
This function returns the namespace associated with the selected item in the commodity tree view.
GtkTreePath * gnc_tree_model_commodity_get_path_from_commodity(GncTreeModelCommodity *model, gnc_commodity *commodity)
Convert a commodity pointer into a GtkTreePath.
int safe_utf8_collate(const char *da, const char *db)
Collate two UTF-8 strings.
#define DEBUG(format, args...)
Print a debugging message.
#define LEAVE(format, args...)
Print a function exit debugging message.
#define ENTER(format, args...)
Print a function entry debugging message.