GKrellM Plugins

A GKrellM plugin is a shared object file (ends with a .so extension)
which is placed in a plugin directory where GKrellM
can find and load it at program startup time.
Directories searched for plugins are:

Users will probably install plugins into one of the first two directories
while packages for a distribution will probably install under /usr/lib.

The one requirement of a plugin is that it must have a global function named
gkrellm_init_plugin() which returns the address of an initialized GkrellmMonitor
data structure. A basic do nothing
GKrellM plugin would look like this:

where the functions update_plugin() and create_plugin() refer to functions
that will be used in example programs later in this document.
The above define of PLUGIN_PLACEMENT as MON_MAIL will cause the plugin to
appear just above the
mail monitor. You could also choose MON_UPTIME, MON_APM, MON_FS, MON_MEM,
MON_INET, MON_NET, MON_DISK, MON_PROC, MON_CPU, or MON_CLOCK depending
on where you think the plugin looks best. This is an initial placement
because the user can re-place plugins.

Plugin Placement

When multiple plugins specify placement above the same monitor, the order
of the plugins is not deterministic. It depends on the order the plugin.so
was written into the plugin directory and is not sorted.
To give plugins additional
placement control, there are two values that can be added to the placement
parameter (both cannot be used at once):

A flag can be or'ed into a placement value so a plugin can be placed
after a builtin monitor instead of the default before the monitor.
For example, to place a plugin after the file system monitors, use:

#define PLUGIN_PLACEMENT (MON_FS | MON_INSERT_AFTER)

I think a good rule to follow would be
to place a plugin before a particular
monitor when you are doing it for appearance (ie that is where the
plugin looks like it should go), but place the plugin "after" a monitor
when there is a functional similarity between the builtin and plugin.
Otherwise, a plugin which has a functional similarity and really should
be placed right after a builtin monitor may not end up in the right
place if several plugins are asking to be placed in the same position.

Plugins can specify a gravity value
from 0 to 15 in the placement parameter. Think of it as higher gravity
pulling a plugin down in its placement slot.
If there is some reason you prefer your
plugin be biased downwards, then give it gravity like so:

#define PLUGIN_PLACEMENT (MON_APM | GRAVITY(8))

If there is a very strong reason to bias it down, give it gravity 15.
If you want placement with respect to another plugin that has gravity,
then give yours a gravity value just above or below the gravity for the
other plugin.

Compiling a Plugin

If the
plugin is a single source file, it can be compiled into a .so file
and installed with the commands:

When developing a plugin, you don't need to install after each compile.
Just run:

gkrellm -p plugin.so

See demo4 in the gkrellm_demos.tar.gz
file for an example of setting a plugin up with a Makefile.

Coding Style Issues

Referencing Structures: &nbsp &nbsp
GK.XXX_tick members may be referenced, but for portability you
should use gkrellm_ticks() to get a pointer to the GK structure.

It is generally OK to reference other structure members such as
GkrellmChart, GkrellmPanel, GKrellmKrell, GkrellmDecal, GkrellmStyle,
and GkrellmTextstyle members.
But using function calls is preferred if one is available, so check if a
function call will do the job you want.

Declaring Structures: &nbsp &nbsp
Never declare a static structure from gkrellm.h. Always use the
gkrellm_XXX_new0() or gkrellm_XXX_copy() functions.
It is safer to use the copy functions for any GkrellmStyle or
GkrellmTextstyle structures you may need, but use the new0
functions for your GkrellmPanel or GkrellmChart structures.

Avoid using global variable names as much as possible to avoid
collisions with other plugins.

Windows Portability: &nbsp &nbsp
Many plugins can easily be coded in a style which is portable to Windows.
Probably all that will be needed are a conditional include of some header
files, a conditional declaration of the gkrellm_init_plugin() function,
and use of pGK->xxx_ticks instead of GK.xxx_ticks references.
See the demo programs below for examples of this.

Charts

When a chart is created, it must be associated with a
GkrellmChartconfig structure. The chart then has the builtin ability
to be user configured with very little coding effort in the plugin.
However, it is the plugins responsibility to save and load the
configuration state and to possibly connect some callbacks
so it can make adjustments when user configuration changes are made.
The things to know are:

You must have a pointer (normally initially NULL) to a
GkrellmChartconfig structure and pass its address when calling
gkrellm_chart_create() or gkrellm_load_chartconfig().
If the pointer is NULL, either of these routines will create the
GkrellmChartconfig structure and update the pointer.

If you destroy a chart, its associated chartconfig is not destroyed.
This allows a plugin to maintain configuration in case there are
dynamic reasons why a chart might come and go (as in the net
charts appearing and disappearing as interfaces are routed and
unrouted).

If you destroy a chart you may optionally call
gkrellm_destroy_chartconfig() on the config if you no longer have
a use for the config.
But, you should never destroy a chartconfig unless you also are
destroying the chart.

All chart monitors currently in GKrellM consist of a chart
and a panel just below it.
Panel creation is generally more involved
and is discussed later,
but here is an example
demo1.c
which creates a stand alone chart without a panel.
It is heavily commented so it
can be a reasonable tutorial for creating a chart, and it is included
along with the example monitors listed below in
gkrellm2-demos.tar.gz

I must emphasize that
the create function for all monitors is a "create event" function which
will be called for every theme and horizontal size change.
The first_create variable
is true only for the initial creation and should be used to allocate
data and make calls that should be done only once.

After the create function is called,
the background image and pixmaps for drawing on are initialized.
The entire chart is a gtk drawing_area and you get allocated expose
and background pixmaps in the GkrellmChart structure (see gkrellm.h).
You can draw on these pixmaps and drawing_area however you want, or
make local pixmaps to work on and then copy to the chart pixmaps.
The thing to remember is that bg_pixmap has a rendered theme
background image pre-loaded which you probably want to preserve, but
there could be exceptions depending on the type of drawing
done on the chart.
A plugin can have its own chart drawing routines for all drawing or
can use the gkrellm chart drawing routine if it will do the job.

Panels

A chart monitor usually has a panel area below the chart, while a meter monitor
has one or more meter areas and no chart.
The panel and meter areas of monitors are both created by allocating
a GkrellmPanel structure and calling gkrellm_panel_create(). The difference
between them is that they have different theme styles and background
images. So many gkrellm_xxx() functions will operate on the common
GkrellmPanel structure, while others that reference styles and images will
have distinct functions to use for the panel or meter areas. For example,
common functions include gkrellm_panel_create(), gkrellm_panel_configure(),
and gkrellm_panel_destroy(). But panel areas also have their own functions
such as gkrellm_panel_style(), gkrellm_bg_panel_piximage(), etc while the
meter areas have the corresponding gkrellm_meter_style(),
gkrellm_bg_meter_piximage(), etc.

It may be confusing, but the terminology to keep in mind is that while
a GkrellmPanel structure applies equally to a panel area and a meter area of
a monitor (perhaps think of the GkrellmPanel structure as a panel_meter structure),
there are separate style and image sets to associate with these panel
and meter areas.

Panels are created to hold krells, decals, and labels, so
code examples for them will be in the sections below. Finally, a
plugin is actually free to mix chart, panel, or meter areas in any order
or combination in a single plugin so long as you are aware of the
style and image theming implications.

Again, it is important to emphasize that the create_plugin() routine is
a create event which will be called multiple times. Plugins are
expected to re-create each decal or krell they may have every time
the create_plugin() routine is called because the GKrellM rebuild routine
automatically destroys all decals and krells in all panels. However,
this automatic destroy can be overridden if you have a reason to
manage the lists yourself.

Krells

A krell is a pixmap graphic which can be moved across the face of a panel
or meter area.
Krell drawing functions (gkrellm_update_krell() or
gkrellm_move_krell_yoff()) draw to the panel pixmap only. After all
krell and decal drawing is done in a monitor update routine, the changes
should be drawn to the screen by calling gkrellm_draw_panel_layers().
This example program
demo2.c
creates a default meter style krell
with a "Plugin" label for a meter area.

Decals and Decal Buttons

There are two types of decals, pixmap and text, which can be drawn
on a meter or panel area. Decal
drawing functions (gkrellm_draw_decal_text(), gkrellm_decal_text_insert(),
gkrellm_draw_decal_pixmap(), gkrellm_move_decal())
draw to the panel pixmap only. After all
krell and decal drawing is done in a monitor update routine, the changes
should be drawn to the screen by calling gkrellm_draw_panel_layers().
A pixmap decal is a single displayed pixmap frame out of an image
which was drawn as a vertical stack of pixmap frames.
The frame displayed is changed by simply calling the decal draw routine
with a different frame index. A text decal is a single pixmap which can have
text drawn on it.

There are two types of buttons that can be created. There are pixmap decal
buttons which can be created directly out of a GkrellmPiximage or which
can be created by converting an existing pixmap decal into a button.
A pixmap decal can be directly converted into a button because it has a set of
vertical frames from which a in and out button image can be assigned.
The second button type applies if you want
to use a single pixmap text decal (no frames) as a button. To do this
it must be indirectly put into a button. This "putting" operation simply
overlays the text decal with a default pixmap decal button that has
in and out images with transparent interiors so the text decal will show
through.

The basic
sequence to follow is create decals (and krells), and then create buttons.
The buttons may be pixmap decals converted into buttons, text decals put
into overlay buttons, or may be pixmap decal buttons created directly
out of a GkrellmPiximage with gkrellm_make_scaled_button(). Then
gkrellm_panel_configure() should be called so a panel height to
accomodate all the krells, decals, and buttons may be calculated.
Finally, the panel is created. Note: decals may be converted into
buttons after the panel is created as was required with GkrellM 1.2.x.
However, with GKrellM 2.0, most buttons may be created before or after the
panel is created with these exceptions: Buttons made with
gkrellm_make_scaled_button() should be done before the panel is created
so that gkrellm_panel_configure() will know of their size. Otherwise
you will have to explicitely manage the panel size to accomodate the
buttons that will be created. And buttons that must still be created
only after the panel is created are
gkrellm_put_label_in_xxx_button() where xxx is meter or panel because the
label won't exist unless the panel is created.

Having buttons which are created out
of decals may seem unusual, but provides some advantages.
A button can have its pixmap
rapidly switched with the same code that switches the pixmaps for a
normal decal, so it can be efficient to have an animated or state
displaying button. However, note that there is a
gkrellm_set_decal_button_index() call to switch the displayed frame of a
decal button while the frame displayed for a decal pixmap is set via an
argument to gkrellm_draw_decal_pixmap().
Also, since pixmap decals can have transparency and
can overlap, pixmap decal buttons can do the same, and are not
restricted to rectangular shapes (the only complication would be the code
to check for the mouse in the button, see demo4).
Note that this way of creating buttons
out of pixmap decals requires that the images for
the in and out button states (there can be multiple out states)
must be drawn as frames of a single vertical
image - you cannot draw them the more traditional way as separate images.

To demonstrate the decal and decal button features, this example program
demo3.c
will create:

a text decal that will be scrolled in the update routine,

a large scaled button made from the default button image.

a smaller auto hiding scaled button.

a text decal that will be put into an overlay button and the text
toggled when the button is pressed,

a pixmap decal that will be converted into a decal button.

There is an advanced demo4 in the
gkrellm2-demos.tar.gz
tar file which includes
a small test-theme that has plugin specific theme images and
gkrellmrc lines. The screenshots to the left show the default layout and
one of the themed alternatives in the test-theme. Here's the
demo4.c
and the
gkrellmrc_1 for the themed alternative screenshot.

Styles, Text Styles, and Themes

There is a Themes document
that describes a GKrellM theme in detail.
Read this to understand how chart, panel, and meter areas are used
to construct monitors in GKrellM, and how background images are
applied to these areas.

When GKrellM loads a theme, style parameters are initialized
to values set by the theme designer. These parameters are stored in a GkrellmStyle
structure for each of the chart, panel, and meter areas. A GkrellmStyle
structure has information about the default krells, borders for
background images, label positions, margins, and two sets of text styles.
There are functions to access the GkrellmStyle structure for a chart, panel,
or meter area, and there are convenience functions to access each of
the GkrellmTextstyle structures within these GkrellmStyle structures. There are also
functions to access background images for the areas of each monitor. These
styles and images may reference theme wide defaults, but also may
have been customized at the monitor level depending on the theme.
When building a plugin monitor, you typically access the GkrellmStyle and/or GkrellmTextstyle
structures appropriate for the monitor by passing a style_id value
to the style and image functions.
The style_id argument should usually be a value returned from
a gkrellm_add_chart_style() or gkrellm_add_meter_style() call, but
could be DEFAULT_STYLE_ID or a looked up style_id value for other monitors.
But be aware that using a style set for another monitor may preclude
a theme author from customizing your plugin and you may get unexpected
results with some themes.

It is also easy to provide for theming any images you have local to
your plugin.
I suggest putting a short Themes file in the
source directory which documents the image names and gkrellmrc
extensions you create for your plugin.
It's hard to say if theme authors will actually do much
plugin theming, but there certainly will be none if you don't tell
anybody how to do it. See the demo4 for a complete themed plugin
example, and here are a couple of additional fragment examples to
give you and idea of what might be involved in theming a plugin:

You have an image for a button you made for your plugin and
you #include it but want to provide for using a theme authors
substitute:

This foo plugin may be themed by making images and placing them in
a "foo" subdirectory of a theme. The standard images used are:
bg_panel.png
And in addition, this plugin has a themable button image:
button.png

These are the functions you should use to allocate storage for the GKrellM
structures in gkrellm.h. When you allocate a panel structure with
p = gkrellm_panel_new0(), a p->label structure is automatically allocated
for you (and will be freed if you call gkrellm_panel_destroy(p)).
You should not use gkrellm_style_new0() or gkrellm_textstyle_new0()
because if you want a local copy of a style or textstyle to modify,
you should get it by copying an existing style. So, typically,
you would:

Call this function to create a chart.
A created chart packs a drawing_area into an hbox which in turn is
packed into the box argument.
The config arg is the address of a GkrellmChartconfig pointer which
may be initialized to point to a GkrellmChartconfig struct (by calling
gkrellm_load_chartconfig()) or may be NULL. If
it is NULL, a GkrellmChartconfig struct will be automatically allocated and
*config will be updated to point to it.
A background pixmap and an expose pixmap will be allocated
and initialized with a rendered copy of a chart background image
determined by the current theme and the style_id value
(see the demo examples).

void gkrellm_chart_destroy(GkrellmChart *chart);

This function frees all the resources (pixmaps, data arrays, etc) in a
chart structure and it frees the chart structure. It also destroys and frees
chart->panel if it is not NULL.
However, it does not free the chartconfig that was linked to it in
gkrellm_chart_create().

This function provides a convenient way to show or hide a chart
based on a new desired visibility and a current visibility.
It updates *current to TRUE if the chart changes from hidden to
shown and it updates it to FALSE if the chart changes from shown to hidden.
The return value is TRUE if the visibility state was changed and returns
FALSE if the visibility state is unchanged. If there is a
chart->panel, the panel is also hidden or shown.

This function provides a convenient way to show or hide a chart
based on a new desired visibility and a current visibility.
It updates *current to TRUE if the chart changes from hidden to
shown and it updates it to FALSE if the chart changes from shown to hidden.
The return value is TRUE if the visibility state was changed and returns
FALSE if the visibility state is unchanged. If there is a chart->panel,
the panel will also be hidden or shown.

Set the function func to be the draw_chart_function for chart.
The draw_chart_function will be referred to in other parts of this
document and is the function
internal chart routines will call whenever
chartdata is to be drawn onto a charts expose pixmap and to the screen.
The default draw_chart_function for all charts
is an internal routine that simply calls
gkrellm_draw_chartdata() followed by gkrellm_draw_chart_to_screen().
If you want to draw anything extra on a chart (such as labels) then you should
set your own function to be the draw_chart_function. Your function should
draw the chartdata, draw your extra stuff, and
then draw everything to the screen.

Draws text units inside string onto the
chart expose pixmap at positions determined by position codes embedded in
the string. Text units are groups of characters bounded by the position
codes. A position code is a backslash followed by a character.
See Config->General->Info for a list of the position codes.
Drawing is not done to the screen until
gkrellm_draw_chart_to_screen() is called.

These functions zero the data arrays for a chart.
gkrellm_reset_and_draw_chart() also calls the draw_chart_function.

void gkrellm_refresh_chart(GkrellmChart *chart);

This function calls the draw_chart_function. It is automatically called
internally when needed, but you may call it if you want user config changes
to be immediately visible inside of apply functions.

void gkrellm_rescale_chart(GkrellmChart *chart);

This function forces a re-scale and then calls gkrellm_refresh_chart().
Normally rescaling is handled internally and you should not need to call
this function unless you have some special chart scaling needs.

gkrellm_clear_chart() and gkrellm_clear_chart_pixmap() draw
the background source pixmap onto the expose pixmap chart->pixmap
but do not clear the chart data arrays. gkrellm_clear_chart() also
draws the background source pixmap to the screen.

gkrellm_clean_bg_src_pixmap() draws the clean background source
pixmap onto the background source pixmap. The "clean background source
pixmap" will always be a simple render of a theme chart background image
while the "background source pixmap" may additionally have transparency
applied.

Calling this function before calling gkrellm_chart_create() will cause
a chart to be created using the specified bg_image and grid_image
instead of the background and grid images associated with the
plugin's style.

gint gkrellm_get_chart_scalemax(GkrellmChart *chart);

This returns the maximum value that can be shown on a chart.
scalemax will be the current grid resolution times the number of grids
shown on the chart. The return value may not be valid if you call this
function between calling gkrellm_store_chartdata() and
gkrellm_draw_chartdata().

Call one of these two routines for each data set to be drawn on a chart.
There are two default colors (or to be more accurate, colored pixmaps)
provided by each theme which are alternately selected at each call to
gkrellm_add_default_chartdata(). If you want to alter the default order
or provide custom colored pixmaps for data drawing, you can specify them
in gkrellm_add_chartdata(). The src_pixmap must be a
GdkPixmap ** because height changes may re-render the pixmap and the
drawing routines need to be able to reference the changed pixmap. If
you provide a custom src_pixmap you should connect to chart
height changes with gkrellm_chartconfig_height_connect()
and re-render your pixmaps if necessary.
The label arg is used to identify the data being configured in
a chartconfig window.

void gkrellm_alloc_chartdata(GkrellmChart *chart);

This function allocates data arrays for each chart data layer.
The arrays are used for data drawing onto the expose pixmap with the
gkrellm_draw_chartdata() routine and have data stored into them with
gkrellm_store_chartdata(). Call this after you have added chartdata
layers to a chart.

void gkrellm_store_chartdata(GkrellmChart *chart, gulong total, ...);

This function stores data for each chart data layer into the data arrays
allocated with gkrellm_alloc_chartdata(). Following the total arg
there must be as many gulong arguments as there are chart data layers.
The data arrays are used as circular buffers and
the position index is incremented with each call. The default is that
data is assumed to monotonically increase in value. If that is not
the case, then monotonic mode should be turned off with
gkrellm_monotonic_chartdata(). For monotonic data,
a difference between the current data args and the previous data values
is what is actually stored. For non monotonic mode, the current data args
are stored unmodified.
To allow plotting of difference data beginning at any point, the first
call to this routine "primes the pump" and will not store the data.

If the total arg is not zero, then the data values stored are
scaled assuming that the total should be the maximum of the
chart. This allows data to be plotted as a percentage of a total
and also accounts for timing jitters that can cause the total
to vary between data samples.

void gkrellm_draw_chartdata(GkrellmChart *chart);

Call this to draw the data stored with gkrellm_store_chartdata() onto the
data and expose pixmaps.
The chart is not drawn to the screen until
gkrellm_draw_chart_to_screen() is called.

Call this with an argument of FALSE if the data is not monotonically
increasing. Monotonic and non-monotonic data can be mixed on a chart
unless you are using non-zero total args in gkrellm_store_chartdata().

gboolean gkrellm_get_chartdata_hide(GkrellmChartdata *cd);

Gets the current hidden state of a chartdata layer. The hidden state is
a user selectable option for some chartdata layers.

Set characteristics of data drawn on charts. draw_style may have the
values CHARTDATA_IMPULSE or CHARTDATA_LINE.gkrellm_set_chartdata_draw_style_default() sets the draw style to an
initial state only if a user configuration has not been loaded.

flags is a set of bitwise or'ed values which control the
presence of some options in the chart
configuration window. It may have the values CHARTDATA_ALLOW_HIDE
(which will allow the user to hide a chartdata layer) and/or
CHARTDATA_NO_CONFIG_DRAW_STYLE (which prevents the user from being able
to change the draw style).

Use these to create and destroy the chartconfig window. It is best to
create it in response to a user right click in the chart drawing area
(you will need to connect to a callback to get the button events).
You probably will never need to destroy it explicitely since it is
automatically destroyed if its chart is destroyed.

Set or get the current grid resolution. It is usually set by the user
or automatically, but you may need to get it if you need
to make any adjustments when it changes (you need to connect to
grid resolution changes).

Calling this function will enable the user to set grid resolutions in the
chartconfig window. You specify the range of adjustments allowed from
low to high. If map is TRUE, the adjustments will
be constrained to the 1,2,5 or the 1,1.5,2,3,5,7 sequence and the step
arguments will not be used. Chart data must be plotted as integer values,
so if your data is real it must be scaled into integer values before
being stored by gkrellm_store_chartdata(). Whatever that scaling factor
is should also be passed as the spin_factor arg so the resolution
units the user sees will be the same as the data being charted. For
normal unscaled integer data, spin_factor should be 1.0.
digits is the float precision the spin button will have and
width is the width in pixels passed to the spin button create.
If this call is not made, then no grid resolution spin button will show
up in the chartconfig window and you will have to control grid
resolutions with gkrellm_set_chartconfig_grid_resolution().

Bitwise or flag values to control parts of the chartconfig window.
Flag values may be NO_CONFIG_FIXED_GRIDS and/or NO_CONFIG_AUTO_GRID_RESOLUTION
which will prevent the user from changing the fixed grids mode or the
auto grid resolution mode respectively.

These set state values of the chartconfig which are normally user set
in the chartconfig window. But if you have not added a grid resolution spin
button the user will not be able set these and you may want to control
them. If sequence 125 is set to TRUE, the sequence will be 1,2,5 instead
of 1,1.5,2,3,5,7. If auto resolution stick is TRUE, then the auto grid
resolution mode will stick at the peak value encountered instead of
ranging over the 1 to 5 base to peak range.

Saves all the settings in the chartconfig structure cf into the
file referenced by f. config_keyword is the config word
you are using in your save_plugin_config() routine. id is an
extra identifier which will be written if it is not NULL. It should
identify which chart is being saved if your plugin has multiple charts.

The cfp arg is the address of a GkrellmChartconfig pointer which
may be initialized to point to a GkrellmChartconfig struct or may be NULL. If
it is NULL, a GkrellmChartconfig struct will be automatically allocated and
*cfp will be updated to point to it.
Then the config_line is parsed for values to initialize the
config structure to the same state as was written by
gkrellm_save_chartconfig(). max_cd is a failsafe from file
corruption or user editing of the config file and will limit the
number of chartdata layers. It should be the number of chartdata layers
you will be adding after creating the chart.

void gkrellm_chartconfig_destroy(GkrellmChartconfig **cfp);

Call this to destroy a chartconfig, but never call it unless you are
also destroying the chart associated with the chartconfig. The
storage referenced by *cfp will be freed and the pointer set
to NULL.

Call this function to create a panel for a chart or meter monitor and
pack it into the GtkWidget box argument.
The mon is a pointer to the same GkrellmMonitor structure returned by
the plugin's gkrellm_init_plugin() routine.
If a label has been configured for the panel (in the
gkrellm_panel_configure() call), it will be drawn on the panel's background
pixmap.

This function should be called after creating the decals and krells
you will need for a panel, and just before calling
gkrellm_panel_create() to actually create the panel. The purpose
of this routine is to calculate a height for the panel to accomodate the
supplied label argument and all the krells and decals that have
been created.
If label is NULL,
then the calculated height will be sufficient for any decals
and krells and the panel will have no label, which will be desirable
for many panels which have text decals.
If the style arg is a pointer to a GkrellmStyle copy returned from
gkrellm_copy_style(), then it should not be
freed after this call. See how panel1_style is handled
above. This is unlike the GkrellmStyle pointer passed to decal and krell
create routines. If those styles are copies, then they should be freed
after the decal or krell create.

After the function returns, an adjustment of the panel height, decal
positions, or krell y offsets may be made.

These calls are made in anticipation of calling
gkrellm_panel_create(), and may or may not be preceded by
calling gkrellm_panel_configure(). With these you can adjust the height
of the panel that will be created in gkrellm_panel_create() if for
some reason you need a height setting different from the height
gkrellm_panel_configure() would set.
These functions can be useful when calling gkrellm_panel_create() outside
of the create_plugin() function when you want to resize a panel; or
they can be used in cases where you don't call gkrellm_panel_configure()
because you want to set a fixed panel height. The height of all panels
is reset to zero when create_plugin() routines are called at theme changes.

Functions for hiding or showing a panel, or for determining the hidden
state.

void gkrellm_panel_keep_lists(GkrellmPanel *panel, gboolean keep);

When GKrellM is rebuilt at theme or horizontal size changes, the default
behaviour is to destroy a monitor's decal and krell lists before calling the
monitor create function. If you need to manage the lists yourself and
don't want them destroyed by default, call this routine with
a TRUE keep value.

void gkrellm_draw_panel_label(GkrellmPanel *panel);

This function draws the label in the panel->label structure onto the
panel background.
Call this if you have changed
a label or moved its position, but this is an inefficient call and if you
need frequent changes to a label, you should be using a text decal instead
of a label.

The panel label is by default drawn below all panel decals. Call this
function to control when the label is drawn above or below
all panel decals. One application is to make sure panel labels are
visible through transient appearing decals such as alert decals.

void gkrellm_draw_panel_layers(GkrellmPanel *panel);

This function walks through the list of decals and krells in a panel and
draws all that are modified to the screen.

void gkrellm_draw_panel_layers_force(GkrellmPanel *panel);

This function draws all decals and krells in a panel to the screen even
if they are not modified.

Get the theme position settings for panel labels. Use if you want to
position some other object such as text decal similarly to how panel
labels are positions. x_position is a percent of chart width, so
a value of 50 indicates centered. y_off > 0 is the pixel offset from
the top of the panel. If it is zero, then panel labels are placed at the
panel top margin.

This function returns a pointer to a created krell which is also
appended to the panel GList of krells. The image im is rendered to a
source pixmap treated as a vertical stack of frames with a depth
determined by the style->krell_depth. The krell frame that will
be displayed is a function of the horizontal position of the krell (see
the Themes document).
The krell y position is set to the krell_yoff of the style unless
the krell_yoff is < 0. Negative krell_yoff values can be:

-1 &nbsp put the krell inside the panel margins justified to the
top margin.

The panel bottom will be defined by
other decal or krell object placements in the panel. If there are no
other objects in the panel,
krell_yoff of -1 is equivalent to krell_yoff of -3 (centers the krell in
the panel) and krell_yoff of -2 is equivalent to krell_yoff of 0,
The krell x_hot
is set to the style krell_x_hot unless krell_x_hot < 0, which sets the
krell x_hot to half the width of the image im.
If you need to adjust (center, justify, initial negative offset, etc)
the krell y postition
then call gkrellm_move_krell_yoff() after the krell is created.
After a krell is created, the full scale value should be set with
gkrellm_set_krell_full_scale() prior to calling the
gkrellm_update_krell() routine.

Initialize a GkrellmStyle structure with values appropriate for a krell.
If any args are out of range the corresponding parameter will not be set.
This means that the parameter setting
may be selectively omitted by setting the corresponding argument to an out
of range negative number. Note that x_hot may be -1 and yoff values may be
negative. See gkrellm_create_krell() above.
An initial krell y position < 0 can only be set with
gkrellm_move_krell_yoff() after the krell is created.
Additionally:

gkrellm_set_style_krell_values_default() sets each style parameter only
if that parameter has not been custom set in the gkrellmrc with a
StyleMeter or StylePanel line.

gkrellm_set_style_slider_values_default() first copies the image
related parameters of the builtin
slider style into style and then sets the positioning parameters
to the supplied positioning argument values only if the corresponding
parameter has not been custom set in the gkrellmrc. This allows custom
slider positioning while preserving the slider image parameters.

Use these functions to set default values for an extension style for a krell
or slider. See gkrellm_xxx_style_by_name() functions and demo4.

Set the full_scale value. If this value is small with respect to
the panel width and you are creating a chart styled krell, it might help
to smooth out the jerky appearance of discrete valued krell positions
by giving a scaling factor that could typically be 10.
For all meter styled and most chart styled krells, however,
the scaling factor should be 1.

By default, krells have a dynamic range of movement across the full width
of a panel, but you can use this function to change the range of movement.
left and right are the number of pixels to move the margins
in from the left and right panel edges. If this function is called for
an expanded style krell, the krell will have already been created and
the krell pixmaps are not re-rendered to the width
between the left and right margins. A better
way to handle krell margins is to set them with a style and then the
krell pixmaps optionally can be rendered to the width between the krell
margins of the style when the krell is created. This way krell margins and
rendering can be controlled by the themer transparently to your code.

void gkrellm_set_krell_expand(GkrellmStyle *style, gchar *value);

This function is deprecated. Krell expand values should be set up
to be controlled in the gkrellmrc with custom styles.
See the gkrellm_xxx_style_by_name() functions.

This routine draws a frame from the krell source pixmap into the krell
destination pixmap. The x_hot spot of the frame is drawn
at a horizontal position between 0 and the panel width - 1.
The horizontal position is determined by the ratio of the krell update value
to the krell full scale value. Krell update values are assumed to be
monotonically increasing so the actual value used will be the difference
between the current value and the value from the previous call
to gkrellm_update_krell(). If the data is not monotonically increasing
then you must call gkrellm_monotonic_krell_values() after creating the
krell. The krell is not drawn to the screen until
gkrellm_draw_panel_layers() is called.

With these you can destroy a krell and control when it is on the
list of krells to be drawn on a panel.
By removing and inserting krells, you can control
their position in the panel glist and
thus their relative overlapping drawing behaviour.
Note: if a krell is removed from a panel and not destroyed or re-inserted,
there can be a memory leak at theme changes because the krell will not
be in the list of krells where it will be automatically destroyed.
For this situation, you should explicitely manage krell destruction
in create_plugin() routines.

Moves the vertical offset of a krell into its panel. This is a krell
drawing function, so the move will not be drawn to the screen until
gkrellm_draw_panel_layers() is called. If yoffset is negative,
the krell will be moved above the top panel edge so that part or all
of it will not be visible.

These two functions destroy all krells and decals in the panel GLists and
free the lists. The only time you should need to use these is if
you call the create_plugin() routine from within the plugin and you have
not first destroyed the panels in the plugin. If you do this, then
these functions should be called at the top of the
create_plugin() routine if the first_create variable is FALSE.
If any decals in the decal
list are also decal buttons, then gkrellm_destroy_decal_list() will also
destroy the buttons.

These functions return a pointer to a created text decal which is also
appended to the panel GList of decals. The decal pixmap
is allocated with a size based on the supplied
arguments. With gkrellm_create_decal_text() the string
argument is not an initialization string for the decal but
is used for vertical text extent sizing
(using the GkrellmTextstyle font ts->font), and the width extent of the
string is used for the decal width if the argument w = 0.

With gkrellm_create_decal_text_with_height() (new in 2.1.11) the
decal height and width are explicitely set, but
because of the font differences between GdkFont and Pango, the last argument
to this function is not compatible between GdkFont and Pango GKrellM
versions, so use this function with care.
y_ink is the pixel offset from the top of the glyph to the first
ink pixel (ie it is the top padding), while y_baseline is the offset
from the top of the glyph (uppermost ink pixel) to the origin used for
drawing and ascent/descent measurements.

For both functions if there is a
non-null style argument and w < 0 then the decal
width will be the full GKrellM width minus the left and right margins.
x < 0 sets the decal x position to the style left margin,
and y < 0 sets the decal y position to the style top margin. After
the decal is created, the x and y values may be adjusted.

Call this function to draw a string into a text decal pixmap. For gkrellm
versions < 2.2.0, draws
occur only if the value argument changes between successive calls unless
the value is -1, in which case draws will always occur.
With version 2.2.0, the value argument is ignored and the string is internally
checked for changes to decide if the draw should occur.
The string may be drawn with an offset into the pixmap if
decal->x_off is
set prior to the call (with 2.2.0, use gkrellm_decal_text_set_offset()),
but gkrellm_decal_text_insert() may also
be useful for drawing with offsets.
The decal pixmap will not be drawn onto the screen until
gkrellm_draw_panel_layers() is called.

New in 2.1.11.
Use these functions to draw with an offset onto a text decal pixmap.
Unlike gkrellm_draw_decal_text(), the gkrellm_decal_text_insert()
function does not
clear the decal prior to drawing text, so successive draws may be made
with different offsets and different fonts or colors. This allows you to
have a multicolored horizontally or vertically scrolling text decal. Use
gkrellm_decal_text_clear() to control the decal clearing.

New in 2.2,0. These functions are for applications where the text in a
text decal is scrolled across the decal extents. As long as the text string
is unchanged, the inherently slow Pango text drawing at each scroll step
can be eliminated. However, Pango drawing will be forced if a scroll
text decal overlaps any other text decal or if a decal of any type is
under a scroll text decal. Use gkrellm_decal_scroll_text_get_size()
to get the pixel size of the extents of the scroll text and note that
this is not the decal size which you get from d->w or in 2.2.0
gkrellm_decal_get_size(). If the text will be vertically scrolled
and you want it horizontally centered,
call gkrellm_decal_scroll_text_align_center(d, TRUE). After setting
the scroll text with gkrellm_decal_scroll_text_set_text(), scrolling
is achieved by calling gkrellm_decal_text_set_offset() and then
gkrellm_draw_panel_layers() at each
scroll step. A Pango redraw is not done at each
gkrellm_decal_scroll_text_set_text() call if the text string is not
changed.
The horizontal or vertical loop calls create an automatic continuous scrolling
loop effect as the decal text offset ranges from 0 to the scroll text size.
These functions can be conditionally compiled in with a

#if defined(GKRELLM_HAVE_DECAL_SCROLL_TEXT)

Pango markup is used to draw the scroll string, so markup attributes may
be used to get colored text.

This function returns a pointer to a created pixmap decal which is also
appended to the panel GList of decals. The pixmap argument is used as
a vertical set of source frames of the given depth and drawing
a pixmap decal
consists of supplying a frame number of the pixmap to the drawing routine.
If the style argument is not NULL and x < 0, then
the decal is positioned at the left or right margin depending on the
style label_position being < or >= 50. If the style argument is not
NULL and y < 0, then the decal y position is set to
the style top margin.
After the decal is created, the x and y values may be adjusted.

New in 2.1.1.
This function returns a pointer to a created pixmap decal which is also
appended to the panel GList of decals if panel is not NULL.
The base decal
frame height will be h_frame unless h_frame is zero, in which
case it will be the
height of the image im divided by depth.
The final real frame height will be the base frame height times the user
set theme scale.
If the style argument is not NULL and x < 0, then
the decal is positioned at the left or right margin depending on the
style label_position being < or >= 50. If the style argument is not
NULL and y < 0, then the decal y position is set to
the style top margin.
After the decal is created, the x and y values may be adjusted.

Call this function to draw a decal source pixmap frame into the decal pixmap.
Draws occur only if the frame argument changes between successive calls,
and the decal pixmap will not be drawn onto the screen until
gkrellm_draw_panel_layers() is called.

Moves the x,y position of a decal in its panel. This is a decal
drawing function, so the move will not be drawn to the screen until
gkrellm_draw_panel_layers() is called.

void gkrellm_decal_on_top_layer(GkrellmDecal *d, gboolean top);

The default is for krells to be drawn on top of decals, but calling this
function with top TRUE will cause a decal to be drawn on top of
krells. The layer change will not be drawn to the screen until
gkrellm_draw_panel_layers() is called.

This function provides a way to paste a decal onto a chart. If the decal is
for a chart only and will not be used on a panel, then the decal should be
created with a NULL panel pointer (otherwise you would have to remove the
decal from the panel). Before drawing the decal on a chart, you may call
gkrellm_draw_decal_pixmap() or gkrellm_draw_decal_text()
with a NULL panel pointer to setup the decal with the right pixmap frame
or text. Then the results can be drawn on a chart with
gkrellm_draw_decal_on_chart(), which should be done as part
of a chart drawing routine that ends up by calling
gkrellm_draw_chart_to_screen().
Decals are not automatically managed in a decal list for charts,
so your create_plugin() routine should handle destroying any decals not
in a panel to avoid memory leaks at theme changes.

With these you can destroy a decal and control when it is on the
list of decals to be drawn on a panel.
By removing and inserting decals, you can control their position in the
panel glist and thus their relative overlapping drawing behaviour.
Note: if a decal is removed from a panel and not destroyed or re-inserted,
there can be a memory leak at theme changes because the decal will not
be in the list of decals where it will be automatically destroyed.
For this situation, you should explicitely manage decal destruction
in create_plugin() routines. A decal may not be removed after it is
converted into a decal button.

If you destroy a decal that has been converted into a decal button, then
the decal button will also be destroyed.

This is probably the best and most flexible way to make a button as long
as you are not making a text decal button or a button using frames out of
the builtin gkrellm_decal_misc_pixmap(). If image is NULL, a builtin
default button image with two frames (an out and a pressed frame) is used.
If you use your own image, there may be more than 2 frames specified
with depth . If auto_hide is TRUE, the button will be
visible only when the mouse is in the panel. If set_default_border
is TRUE, the button will be scaled with default border values of 1,
otherwise it will be scaled with the image border values (which
will be zero unless you have set them).
cur_index is the initial
button out frame and may be changed with gkrellm_set_decal_button_index() if
the image has more than 2 frames to realize animated or state
indicating buttons. Frame changes
will not show on the screen until gkrellm_draw_panel_layers() is called.
pressed_index
is the button frame displayed when the button is pressed.
If w
and h are zero, the button size will be the image size.
The actual button size will be different from an argument specified size or
image size if the user has set a theme scale other than 100.
If image is NULL, depth, cur_index, and
pressed_index are ignored.
See demo3 for example usage.

After a pixmap decal has been created, the decal may be converted to
a decal button. Recall that a pixmap decal has a source pixmap
divided into a vertical stack of frames.
cur_index is the initial
button out frame and may be changed with gkrellm_set_decal_button_index() if
the image has more than 2 frames to realize animated or state
indicating buttons. Frame changes
will not show on the screen until gkrellm_draw_panel_layers() is called.
pressed_index
is the button frame displayed when the button is pressed.
See demo3 for example usage.

This function creates a two frame decal out of normal_image and
pressed_image and then turns it into a decal button. It is used to implement
panel and meter buttons below and is mainly an internal function but
is made available just in case. This function is not intended to be used
to create plugin buttons directly out of loaded images because the
overlay button type is not considered when sizing a panel with
gkrellm_panel_configure(). I strongly suggest that plugins not use this
function.

Instead of converting a decal directly into a button, these functions create
a decal button in a panel or meter area which is overlayed onto an
existing decal. The created decal
button is a rectangular border around a transparent interior so the
existing decal shows through, which is useful for indirectly converting a
text decal into a decal button.
If margin is not NULL, then the size of the
transparent interior of the created button will be padded with the margin
values.

These functions are similar to putting a decal into a button, except that
the created decal button is overlayed onto the panel or meter label.
The button can be padded horizontally around the label with the pad
argument. If there is no label on the panel or meter, the entire panel
or meter area is placed inside the overlay button.
These functions can only be called after panel has been created.

If you have a non-rectangular button it will be pressed when the
mouse is clicked in its decal rectangular bounding box unless you
provide your own "in button" routine to test the mouse position. Use this
function to set your in button routine to do the test. The func will be
called like this:
(*func)(GkrellmDecal *decal, GdkEventButton *ev, gpointer data) and your func
should return TRUE if the ev->x and ev->y is in the active area of the
button's decal. The default in button callback is gkrellm_in_decal()
and you may call it directly (probably useful for checking for the mouse in
a decal drawn on a chart). See demo4 for example usage of these functions.

Change the callback function which will be invoked when a button is
clicked. If a gkrellm_decal_button_right_connect() is made, then
the button can invoke a distinct callback with a right button
click. The callback function prototype is
&nbsp &nbsp void (*func)(GkrellmDecalbutton *button, gpointer data);

These functions control button visibility and sensitivity in a panel.
Hiding a button also makes it insensitive.
To move a button's position in its
panel, use gkrellm_move_decal() and move the decal used to create
the button.

Use this function to select the decal frame to display if a decal has been
converted to a button. Do not call gkrellm_draw_pixmap_decal() to change
the displayed frame for decal buttons, and you should not call this function
with frame equal to the pressed_frame.

GkrellmDecalbutton *gkrellm_decal_is_button(GkrellmDecal *decal);

Search the button list to see if decal is a button decal. If so, return
a pointer to the GkrellmDecalbutton, otherwise return NULL.

These functions provide a way for plugins to use themed variations of any
local images they may have.

The subdir
of the current theme directory is searched for name.png
(or name.jpg, etc). If found it is loaded and *im is
updated to point to it.
If not found, the xpm image is loaded (or the inline GdkPixbuf
data is used if using gkrellm_load_piximage_from_inline()) and
*im updated.
If *im is not NULL at entry, the image it points to is
destroyed before it is updated
to the newly loaded image. It is not destroyed if
a new image cannot be loaded.
copy_pixels is passed directly to gdk_pixbuf_new_from_inline() if
the inline data is used.
Since im usually will be a static variable, image maintenance can
be automatically handled with no memory leaks as themes change, but beware
if im is declared automatic where it should be initialized to NULL.
If a new image is successfully loaded, the function returns TRUE, otherwise
FALSE.
The subdir name should be the same name as referenced by your
style_id, which must be added in your gkrellm_init_plugin() routine with
a call to
gkrellm_add_meter_style() or gkrellm_add_chart_style(),
see above demo2.c.
Theme alternative (name_X.png) images in the subdir are handled.

For example, your plugin uses a custom image
(krell, button, decal) you created, call it foo.xpm, but you want theme
authors to be able to provide a themed substitute (foo.png, foo.jpg, etc)
in their theme.
A code fragment would look like:

With these arguments gkrellm_load_piximage() will try to load
foo.png (or .jpg etc) or foo_N.png (if a theme alternative N is selected)
from the my_plugin_style_name subdirectory of the current theme
directory. If the theme author has created this custom image it will be
loaded, otherwise the included foo_xpm
image will be loaded. foo_image will be updated to point to whichever
image is loaded. If foo_image is not NULL at entry, it is
automatically destroyed prior to loading the new image.

Reads image data from a file, #included xpm data, or inline
GdkPixbuf data and creates a
GkrellmPiximage structure. The border values are initialized to zero.
copy_pixels is passed to gdk_pixbuf_new_from_inline().

These functions scale a temporary copy of a GdkPixbuf to size w
and h and then update *pixmap
and *mask to point to a pixmap and mask copy of the scaled pixbuf.
If scaling a piximage to a pixmap, the scaling operation looks at the border
values of the piximage and scales the pixbuf in stages so that border
regions are scaled properly. If *pixmap is
not NULL when this function is called, the pixmap it points to is freed.
If w or h is <= zero then the rendered width or height
will be the image width or height.

If the border values of a piximage are zero, then
gkrellm_scale_piximage_to_pixmap(image, ...) is equivalent to
gkrellm_scale_pixbuf_to_pixmap(image->pixbuf, ...)

These functions scale a pixbuf to a new w_dst and h_dst
and draw the resulting pixbuf on the drawable at location
x_dst and y_dst. The source
pixbuf is not altered. If pasting a piximage, the scaling accounts for
the piximage borders.

If the destination pixmap or bitmap exists and is the same size as the
source, then draw the source onto the destination. Otherwise,
free the destination pixmap or bitmap, allocate a new destination
the same size as the source, and then draw the source onto the destination.
If the source pointers are NULL, the destination drawable will simply
be freed.

This function allows a plugin to retrieve an integer value which may be
specified in a theme gkrellmrc file. If the integer is specified in the
gkrellmrc, the function returns TRUE, else FALSE.
Say a plugin pluginname
is designed to allow variable horizontal positioning of a button
in a panel and wants to check if a theme author has specified this
positioning. The plugin writer must make up a name to look for and should
document this (in a plugin Themes file) so theme makers will know the
variable can be specified in the gkrellmrc.
It's a good idea to embed the
plugin name into the integer name to avoid collisions with other monitors.
For example, if code is
written like this:

Then the plugin author should document in his Themes file that
an integer variable pluginname_button_x may be specified in a theme's
gkrellmrc with a line like:

set_integer pluginname_button_x = n

gchar *gkrellm_get_gkrellmrc_string(gchar *string_name)

This function allows a plugin to retrieve a string which may be
specified in a theme gkrellmrc file. If the string is found in the
gkrellmrc, a pointer to an allocated (g_strdup()) copy of the string
is returned, else NULL is returned.
Say a plugin pluginname
wants to use a string it will interpret as a color value string
and wants to check if a theme author has specified this
color. The plugin writer must make up a name to look for and should
document this (in a plugin Themes file) so theme makers will know the
color can be specified in the gkrellmrc.
It's a good idea to embed the
plugin name into the color string name to avoid collisions with other monitors.
For example, if code is
written like this:

These functions allows a border specified in a theme gkrellmrc file to
be applied to a a custom background image a plugin may use.

If the border was set, gkrellm_set_gkrellmrc_piximage_border() applies
the border to image and if style is not NULL,
copies the border values into its border. If the border was not set
the style border values are set to zero.

If the border was set,
the gkrellm_get_gkrellmrc_piximage_border() function will
apply the border to image and copy
the border values into border if it is not NULL.

The sequence probably will be:

A plugin coder designs into the plugin the capability to use an
alternate custom background for a subarea of a panel or for an entire
panel. This makes sense for plugins that create multiple panels and it
would be cool for one of them to be able to have a background different
from the others.

The plugin coder makes up a name for this image and loads it by calling
gkrellm_load_piximage(). This will load the custom image if it exists in
the theme.

If it does exist, then a call to gkrellm_set_gkrellmrc_piximage_border()
should also be made to access a possible border specification for it the theme
author may have put in the gkrellmrc.

The plugin coder should document that his plugin can be themed so
theme makers can know what can be done. For example, say the image name
that was made up was bg_special.png, and the
border name associated with it was set up to be pluginname_bg_special.
Then the plugin coder should
document in a Themes file
that theming capability exists for his plugin by specifying these names.
The theme maker sees the documentation and knows he can create a
theme image pluginname/bg_special.png and can specify a border for it
in his gkrellmrc with a line like:

You probably never need to call this since height adjustsments are
automatic when charts or panels are created or destroyed. However
if you ever change a height in an unusual way, you may need to call
this function to let GKrellM know the height has changed. If you have
to call this function, then you may also have to call
gkrellm_pack_side_frames(). Coding like this is not recommended.

These functions pop up a dialog with an informative message string displayed
and a single "OK" button. The dialog from gkrellm_message_dialog() appears
over the gkrellm window and does not block. The dialog from
gkrellm_config_message_dialog() appears over the config window and blocks
user input until the OK button is pressed.

gkrellm_pack_side_frames() renders the side frames to the current monitor
height. It is called automatically after all the create functions or
config apply functions are called. It is also called automatically if you
use the hide/show functions at other times.
If you change a monitor's height in some other way such that you need
to call gkrellm_monitor_height_adjust(), then you should also pack the frames.

If hiding or showing multiple charts or panels, freeze the side frame
packing before you start and thaw it when you are done for efficiency, unless
it is code inside of an apply. Do not call gkrellm_pack_side_frames() if
you do a freeze and a thaw.

gkrellm_get_style_margins() returns a pointer to a GkrellmStyle's GkrellmMargin
struct which has the members left, right, top, bottom.
These margins are generally used for decal or label placements.
Krells have their own independent left and right margin settings.

This routine returns the top and bottom margin associated with
a style. The values are from the GkrellmStyle's GkrellmMargin struct.

void gkrellm_config_modified(void);

Calling this function marks the user_config modified. If it
is still modified when GKrellM exits,
the user_config file will be automatically written.
Writting the user_config means the save_config()
function for all builtins and plugins will be called.

Note that the user_config file is always written after all apply_config()
functions are called, so there is no need to call this
from inside those functions. The apply_config() functions
are always called when the main
config window Apply or OK buttons are clicked.

Normally when a plugin is disabled, the only clue the plugin gets that
this has happened is that its update function stops being called. This is
adequate for plugins that simply monitor by reading some data, but plugins
that additionally are designed to control some resource can connect to
the disable event so they may free the resource. The connect call should
be made in the create_plugin() function.

When a plugin is enabled, its create function will be called.
So if the disable plugin function will reset a flag, then the create function
can know when to re-acquire any resources.

Allocates, initializes, and returns a pointer to an alert structure.
The alert will not get triggered until it has been activated
in one of two ways: the user applies an alert
config window for the alert which sets alert trigger values, or
gkrellm_alert_set_triggers() is
called to set the values for a hardwired alert.
NOTE: if a config window for the alert
is opened and the user does not initially activate the alert or if
he destroys the alert, the pointer to the alert will be reset to NULL.
This way you can always check the value of the alert pointer for NULL to
know if the alert is active.
So, typically you would have a Gtk button callback
in your plugin config window which would check an alert pointer for NULL
and if so, then initialize it with gkrellm_alert_create().
Then connect callbacks to the alert and call gkrellm_alert_config_window().
unit_string - identifies the alert units.check_high - TRUE if the alert is to have upper limits.check_low - TRUE if the alert is to have lower limits.do_updates - TRUE to have the alert decals automatically drawn
to the screen. FALSE if your update routine calls gkrellm_draw_panel_layers()
every timer_tick anyway and you want to be efficient.
The alarm or warning values are selected with a spin button which is
created using the
max_high, min_low, step0, step1, digits arguments.

Turns an alert off. The alert will be retriggered at the next check
if alert conditions still exist. Use gkrellm_reset_alert_soft()
if you are turning off the alert for some temporary reason such as to
manage some panel drawing. This will prevent unwanted extra alarm or
warn command execution when if the alarm is retriggered at the next check.

These connect the plugins callback functions for alert triggering or
alert config events.
An alert_trigger event occurs when gkrellm_check_alert() is called and a
limit test triggers either an alarm or warning.
An alert_config event occurs when the user applies or deletes an alert
config window. The alert is being applied if the alert is activated and
the alert is being deleted if the alert is not activated.
The callback prototype for these first two events is:

(*func)(GkrellmAlert *a, gpointer data);

An alert_config_create event occurs when an alert config window is created
and may be used to add custom options to an alert config window. The
callback prototype is:

(*func)(GkrellmAlert *a, GtkWidget *vbox, gpointer data);

A alert_command_process event occurs when an alarm or warning command is about
to be executed and may be used to process the command string. In the callback,
a src command string is expected to be copied to a dst buffer of len bytes
with possible expansions or substitutions. The callback prototype is:

(*func)(GkrellmAlert *a, gchar *src, gchar *dst, gint len);

void gkrellm_render_default_alert_decal(GkrellmAlert *alert);

When an alert is triggered, the callback in a plugin should set the
position and size of the alert decal to be displayed and should render
the image to be used. The image rendering should be done with
this function unless the plugin uses its own alert image.

gboolean gkrellm_alert_decal_visible(GkrellmAlert *alert);

Returns TRUE is the alert decal for the given alert is visible. It will
be visible if the alert is currently triggered.

void gkrellm_alert_config_window(GkrellmAlert **alert);

Creates an alert config window for the alert.

void gkrellm_alert_window_destroy(GkrellmAlert **alert);

Destroys the alert config window created by gkrellm_alert_config_window().

Saves all the settings in the structure alert into the
file referenced by f. mon_keyword is the config word
you are using in your save_plugin_config() routine. name is an
extra identifier which will be written if it is not NULL. It should
identify which alert is being saved if your plugin has multiple alerts.

void gkrellm_load_alertconfig(GkrellmAlert **ap, gchar *config_line);

The ap arg is the address of a GkrellmAlert pointer which
may be initialized to point to a GkrellmAlert struct or may be NULL. If
it is NULL, a GkrellmAlert struct will be automatically allocated and
*ap will be updated to point to it.
Then the config_line is parsed for values to initialize the
GkrellmAlert structure to the same state as was written by
gkrellm_save_alertconfig().

void gkrellm_alert_set_delay(GkrellmAlert *alert, gint delay);

Set the delay in seconds that an alert limit condition must exist before
an alert will be triggered. Use this for alerts which do not have a user
config.

Set the high and low alert delay range limits which can
be set by the user in an alert config window. The step value
should be the interval in seconds between calls to gkrellm_check_alert()
for this alert.

Create a style for a chart or meter monitor
and return a style_id value
that can be used to access text parameters, krell parameters, and
theme images for the style.
These calls must be made in the gkrellm_init_plugin() routine so the style will
exist when themes are loaded. Creating a plugin style should be
considered a good thing (close to mandatory).

mon is a pointer to the GkrellmMonitor
structure that must be returned by the gkrellm_init_plugin() routine.

name is a string that should not have any spaces and should not
conflict with style names for any other plugin or builtin monitor. It is
the name used to link theme settings to your plugin and is used as the
theme subdirectory name and as the theme gkrellmrc style name qualifier in
StyleChart, StylePanel, or StyleMeter.

For example, if you have a plugin foo and make the call
gkrellm_add_meter_style(mon, "foo"), then a theme author can put in
the gkrellmrc the line:
&nbsp &nbsp &nbsp StyleMeter foo.textcolor = orange black shadow
which would set the text color for a plugin to orange independent of other
monitors. Of course the plugin code would first have to access this
color (using gkrellm_meter_textstyle(style_id)).

Images (backgrounds, krells, etc) customized for a plugin will be searched
for in each theme directory under a subdirectory of the same
name as passed to gkrellm_add_meter_style() or
gkrellm_add_chart_style().
These images
can then be accessed in a plugin by passing the returned style_id to
gkrellm_xxx_style(),
gkrellm_xxx_textstyle(), and gkrellm_xxx_piximage() functions (see below).

A plugin should make only a single call to either
gkrellm_add_meter_style() or gkrellm_add_chart_style().

Use these functions to look up a style_id value by name if you have not
saved the value returned from your gkrellm_add_xxx_style() calls.
They also can be used to get style_id values for other monitors
in GKrellM if the name argument is the style name as registered by
gkrellm_add_chart_style() or gkrellm_add_meter_style() in the other monitors.
With plugins having their own style_id, using styles set for other monitors
should be avoided. At least using a borrowed style should only be a
fallback after checking that a theme author has no customizations for
your plugin with gkrellm_style_is_themed().

void gkrellm_copy_style_values(GkrellmStyle *src, GkrellmStyle *dst);

Copies structure values from dst to src.

gboolean gkrellm_style_is_themed(GkrellmStyle *style, gint query);

If query is zero, return TRUE if there have been
any custom settings for the style in the gkrellmrc. Set query
to a bitwise ored set of GKRELLMSTYLE flags to check if specific style
parameters have been themed in the gkrellmrc. For example:
&nbsp &nbsp gkrellm_style_is_themed(style, GKRELLMSTYLE_KRELL_YOFF);
will return TRUE only if the krell_yoff for style was set in the
gkrellmrc. See gkrellm.h for the set of GKRELLMSTYLE values.

These functions return pointers to GkrellmStyle structures appropriate for
use with a meter or panel area, a chart, or the krell slider.
The style_id argument should usually be a value returned from
a gkrellm_add_chart_style() or gkrellm_add_meter_style() call, but
could be DEFAULT_STYLE_ID or a looked up style_id value for other monitors.

If style_name is the same name as registered with a
gkrellm_add_xxx_style() call, then these functions return
the associated GkrellmStyle. Additionally, style_name may add a
".custom_name" extension to access a possibly themed custom style.

For example, if a plugin made the call gkrellm_add_meter_style("frump")
then it can make the call gkrellm_meter_style_by_name("frump")
to get its default style. And it can also make the call
gkrellm_meter_style_by_name("frump.gas-gauge") which will return
a custom "gas-gauge" style if it exists, otherwise it will return the
default "frump" style. The gas-gauge style will exist if the themer
has put in his gkrellmrc a line like:

&nbsp &nbsp &nbsp StyleMeter frump.gas_gauge.krell_left_margin = 10

This provides for using custom styles which can easily be themed
transparently to your code.
It is probably most convenient when you are using extra krells, but
you could use any of the custom Style parameters in a plugin defined way.
Just document their use in a Themes file so a theme author will know about
them. The convenience of this is that you can eliminate many
gkrellm_get_gkrellmrc_string() and
gkrellm_get_gkrellmrc_integer() calls and allow
theme authors to set the custom Style
values using the familiar StyleMeter or StylePanel syntax.

Coding example: your plugin meter with a "frump" style name needs to create an
extra krell for which you #include a default image krell_gas_gauge.xpm
requiring some default
Style values. But you want to allow a themable krell image with themed
specified Style values in the gkrellmrc. You document
in a Themes file that a themer may make the custom krell image
frump/krell_gas_gauge.png and may have custom style lines in his gkrellmrc
like:

These functions return pointers to the GkrellmTextstyle structures appropriate
for use on a chart, panel or meter area.
The style_id argument should usually be a value returned from
a gkrellm_add_chart_style() or gkrellm_add_meter_style() call, but
could be DEFAULT_STYLE_ID or a looked up style_id value for other monitors.

These functions return pointers to the theme image backgrounds for
the various background areas in GKrellM.
The style_id argument should usually be a value returned from
a gkrellm_add_chart_style() or gkrellm_add_meter_style() call, but
could be DEFAULT_STYLE_ID or a looked up style_id value for other monitors.

These functions return pointers to the theme krell images.
The style_id argument should usually be a value returned from
a gkrellm_add_chart_style() or gkrellm_add_meter_style() call, but
could be DEFAULT_STYLE_ID or a looked up style_id value for other monitors.

Returns a pointer to the GK ticks structure which has the timer tick members
timer_ticks, second_tick, and so on. Plugin code will be more portable
to other environments such as Windows if you use this function and make
refrences such as pGK->second_tick rather than direct GK references like
GK.second_tick.

gint gkrellm_plugin_debug(void)

Returns the debug value which a user can set with the -debugN option.
A plugin may hijack a particular integer value for debugging which will
hopefully be unique to the plugin.

The values returned are:
update_HZ - number of times per second update routines are called.
allow_scaling - if image scaling should be allowed at width changes.
chart_width - user set chart width in pixels.
theme_path - a pointer to the current theme (is pointer to '\0' if the
current theme is the default theme.
theme_scale - is a user set scaling factor for decal and krell image
sizes.

Returns a pointer to the users home directory. A cached pointer is returned
after the first call.

gboolean gkrellm_dup_string(gchar **dst, gchar *src);

A very useful and safe way to duplicate strings.
First, if *dst is not NULL and compares equal to
src, no duplication is done and FALSE is returned.
Otherwise, if *dst is not NULL it is freed with g_free().
Finally, src is duplicated into *dst with g_strdup()
and TRUE is returned.

Make a config file name possibly qualified with a config suffix if one of the
alternate config options were specified on the command line. The returned
string is in allocated memory, so g_free() it when you are done with it.

gkrellm_make_config_file_name() returns the string "dir/config" if there
is no config suffix. If there is a config suffix, the returned string will
be "dir/config-suffix" where suffix will be the command line -c argument or
the hostname if the -force-host-config option was run.

gkrellm_make_data_file_name() returns the string
"/data/subdir/name"
if there is no config suffix. If there is a config suffix, the returned string
will be "/data-suffix/subdir/name". If subdir or name
are NULL, there will be no corresponding path component in the returned string.
The subdir will be created if it does not exist.

struct tm *gkrellm_get_current_time(void);

Returns a pointer to a static struct tm having the current time.
The current time is updated at each GK.second_tick.

These are useful for creating notebook pages in configuration windows. After
you make a notebook with
&nbsp &nbsp tabs = gtk_notebook_new();
just call:
&nbsp &nbsp vbox = gkrellm_gtk_framed_notebook_page(tabs, "Tab Name");
And you have a vbox inside a labeled notebook page you can put widgets in.

gchar *gkrellm_gtk_entry_get_text(GtkWidget **entry);

Reads the text from an entry and returns a pointer to the text with
leading white space skipped.

This could greatly simplify your spin button creation and maybe cover 90%
of your spin button needs.
If right_align is FALSE, a spin button followed by the label
is packed aligned to the left into box.
If right_align is TRUE, the label followed by a spin button is
packed aligned to the right into box.
The value, low, high, step0, step1 values are used
for creating the adjustment. The
number of significant digits is set with digits. If width is
greater than zero it sets the pixel usize of the spin button. If data
is not NULL it will be passed to your callback cb_func().
If it is NULL, then the created gtk_spin_button_new() pointer will be passed.

Creates a labeled check button,
sets its active state, and packs it into box using the Gtk
expand, fill, and pad values.
The cb_func is connected to the "clicked" signal.
The button arg may be NULL if you don't need the button pointer.

Creates a labeled button,
and packs it into box using the Gtk
expand, fill, and pad values.
The cb_func is connected to the "clicked" signal.
The button arg may be NULL if you don't need the button pointer.

This is a function you can use to get font and formatting variations
into Info/Help pages of a plugin config.
text is a GtkWidget created with gkrellm_gtk_scrolled_text_view(),
string is a
pointer to an array of string pointers.

These return a vbox widget packed into a labeled frame. The frame is packed
with gtk_box_pack_start() or gtk_box_pack_end()
into the supplied box with frame_expand expand and fill values.
frame_border_width - border around outside of frame.vbox_pad - pad between widgets to be packed in the returned vbox.vbox_border_width - border between returned vbox and frame.