Revision 26981 (by juha, 2008/05/22 15:04:01) Fixed: bug #4096 - Orage freezes on double click
Actually it was not a freeze but a multiple start.
/* vim: set expandtab ts=4 sw=4: */
/*
 *
 *  Copyright © 2006-2007 Juha Kautto <juha@xfce.org>
 *
 *  it under the terms of the GNU Library General Public License as published 
 *  by the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *  Authors:
 *      Juha Kautto <juha@xfce.org>
 *      Based on XFce panel plugin clock and date-time plugin
 */

#include <config.h>
#include <sys/stat.h>
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdkevents.h>

#include <libxfce4util/libxfce4util.h>
#include <libxfcegui4/libxfcegui4.h>
#include <libxfce4panel/xfce-panel-plugin.h>

#include "orageclock.h"

/* -------------------------------------------------------------------- *
 *                               Clock                                  *
 * -------------------------------------------------------------------- */

static void utf8_strftime(char *res, int res_l, char *format, struct tm *tm)
{
    char *tmp = NULL;

    /* strftime is nasty. It returns formatted characters (%A...) in utf8
     * but it does not convert plain characters so they will be in locale 
     * charset. 
     * It expects format to be in locale charset, so we need to convert 
     * that first (it may contain utf8).
     * We need then convert the results finally to utf8.
     * */
    tmp = g_locale_from_utf8(format, -1, NULL, NULL, NULL);
    strftime(res, res_l, tmp, tm);
    g_free(tmp);
    /* Then convert to utf8 if needed */
    if (!g_utf8_validate(res, -1, NULL)) {
        tmp = g_locale_to_utf8(res, -1, NULL, NULL, NULL);
        if (tmp) {
            g_strlcpy(res, tmp, res_l);
            g_free(tmp);
        }
    }
}

static void oc_tooltip_set(Clock *clock)
{
    char res[OC_MAX_LINE_LENGTH-1];

    utf8_strftime(res, sizeof(res), clock->tooltip_data->str, &clock->now);
    if (strcmp(res,  clock->tooltip_prev)) {
        gtk_tooltips_set_tip(clock->tips, GTK_WIDGET(clock->plugin),res, NULL);
        strcpy(clock->tooltip_prev, res);
    }
}

static gboolean oc_get_time(Clock *clock)
{
    time_t  t;
    char    res[OC_MAX_LINE_LENGTH-1];
    int     i;
    ClockLine *line;

    time(&t);
    localtime_r(&t, &clock->now);
    for (i = 0; i < OC_MAX_LINES; i++) {
        line = &clock->line[i];
        if (line->show) {
            utf8_strftime(res, sizeof(res), line->data->str, &clock->now);
            /* gtk_label_set_text call takes almost
             * 100 % of the time wasted in this procedure 
             * Note that even though we only wake up when needed, we 
             * may not have to update all lines, so this check still
             * probably is worth doing
             * */
            if (strcmp(res,  line->prev)) {
                gtk_label_set_text(GTK_LABEL(line->label), res);
                strcpy(line->prev, res);
            }
        }
    }
    oc_tooltip_set(clock);

    return(TRUE);
}

static gboolean oc_get_time_delay(Clock *clock)
{
    clock->timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
            , clock->interval, (GSourceFunc)oc_get_time, clock, NULL);
    oc_get_time(clock);
    return(FALSE); /* this is one time only timer */
}

gboolean oc_start_timer(Clock *clock)
{
    time_t t;
    gint   delay_time =  0;
    /* if we are using longer than 1 minute (= 60000) interval, we need
     * to delay the first start so that clock changes when minute or hour
     * changes */

    oc_get_time(clock);
    time(&t);
    localtime_r(&t, &clock->now);
    if (clock->interval >= 60000) {
        if (clock->interval >= 3600000) /* match to next full hour */
            delay_time = (clock->interval -
                    (clock->now.tm_min*60000 + clock->now.tm_sec*1000));
        else /* match to next full minute */
            delay_time = (clock->interval - clock->now.tm_sec*1000);
    }
    if (clock->delay_timeout_id) {
        g_source_remove(clock->delay_timeout_id);
        clock->delay_timeout_id = 0;
    }
    if (clock->timeout_id) {
        g_source_remove(clock->timeout_id);
        clock->timeout_id = 0;
    }
    clock->delay_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
            , delay_time, (GSourceFunc)oc_get_time_delay, clock, NULL);
    /* if we have longer than 1 sec timer, we need to reschedule 
     * it regularly since it will fall down slowly but surely, so
     * we keep this running. */
    if (clock->interval >= 60000) {
        if (delay_time > 60000)
        /* let's run it once in case we happened to kill it
           just when it was supposed to start */
            oc_get_time(clock); 
        return(FALSE);
    }
    else
        return(TRUE);
}

static gboolean oc_end_tuning(Clock *clock)
{
    /* if we have longer than 1 sec timer, we need to reschedule 
     * it regularly since it will fall down slowly but surely */
    if (clock->adjust_timeout_id) {
        g_source_remove(clock->adjust_timeout_id);
        clock->adjust_timeout_id = 0;
    }
    if (clock->interval >= 60000) { /* resync it after each 6 hours */
        clock->adjust_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
                , 6*60*60*1000, (GSourceFunc)oc_start_timer, clock, NULL);
    }
    g_free(clock->tune);
    clock->tune = NULL;
}

static gboolean oc_next_level_tuning(Clock *clock)
{
    TimeTuning *tune = clock->tune;
    gboolean continue_tuning = TRUE;

    if (clock->interval == OC_CONFIG_INTERVAL) /* setup active => no changes */
        return(FALSE);
    switch (tune->level) {
        case 0: /* second now; let's set interval to minute */
            clock->interval = 60*1000; 
            break;
        case 1: /* minute now; let's set it to hour */
            clock->interval = 60*60*1000; 
            break;
        default: /* no point tune more */
            break;
    }
    if (tune->level < 2) {
        tune->level++;
        oc_start_timer(clock);
        oc_start_tuning(clock);
    }
    else {
        continue_tuning = FALSE;
        oc_end_tuning(clock);
    }
    return(continue_tuning);
}

static gboolean oc_tune_time(Clock *clock)
{
    /* idea is that we compare the panel string three times and 
     * if all of those are the same, we can tune the timer since we know 
     * that we do not have to check it so often. Time in panel plugin is
     * not changing anyway. So we adjust the timers and check again */
    gboolean continue_tuning = TRUE;
    TimeTuning *tune = clock->tune;

    if (clock->interval == OC_CONFIG_INTERVAL) /* setup active => no changes */
        return(FALSE);
    switch (tune->cnt) {
        case 0: /* first time we come here */
            strncpy(tune->prev[0], clock->line[0].prev, OC_MAX_LINE_LENGTH);
            strncpy(tune->prev[1], clock->line[1].prev, OC_MAX_LINE_LENGTH);
            strncpy(tune->prev[2], clock->line[2].prev, OC_MAX_LINE_LENGTH);
            strncpy(tune->tooltip_prev, clock->tooltip_prev,OC_MAX_LINE_LENGTH);
            break;
        case 1:
        case 2:
        case 3: /* FIXME: two may be enough ?? */
            if (strncmp(tune->prev[0], clock->line[0].prev, OC_MAX_LINE_LENGTH)
            ||  strncmp(tune->prev[1], clock->line[1].prev, OC_MAX_LINE_LENGTH)
            ||  strncmp(tune->prev[2], clock->line[2].prev, OC_MAX_LINE_LENGTH)
            ||  strncmp(tune->tooltip_prev, clock->tooltip_prev
                    ,OC_MAX_LINE_LENGTH)) {
                /* time has changed. But it may change due to bigger time
                 * change. For example if we are checking seconds and time
                 * only shows minutes, this can change if hour happens to
                 * change. So we need to check the change twice to be sure */
                if (tune->changed_once) { /* this is the second trial already */
                    continue_tuning = FALSE;
                    oc_end_tuning(clock);
                }
                else { /* need to try again */
                    tune->changed_once = TRUE;
                    tune->cnt = -1; /* this gets incremented to 0 below */
                }
            }
            break;
        default:
            break;
    }
    if (continue_tuning)
        if (tune->cnt == 3) 
            continue_tuning = oc_next_level_tuning(clock);
        else 
            tune->cnt++;

    return(continue_tuning);
}

void oc_disable_tuning(Clock *clock)
{
    TimeTuning *tune = clock->tune;

    if (tune == NULL)
        return;
    if (tune->timeout_id) {
        g_source_remove(tune->timeout_id);
        tune->timeout_id = 0;
    }
    if (clock->adjust_timeout_id) {
        g_source_remove(clock->adjust_timeout_id);
        clock->adjust_timeout_id = 0;
    }
}

void oc_start_tuning(Clock *clock)
{
    TimeTuning *tune = clock->tune;

    if (clock->interval == OC_CONFIG_INTERVAL) /* setup active => no changes */
        return;
    tune->cnt = 0;
    tune->changed_once = FALSE;
    if (tune->timeout_id) {
        g_source_remove(tune->timeout_id);
        tune->timeout_id = 0;
    }
    tune->timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
            , 2*clock->interval, (GSourceFunc)oc_tune_time, clock, NULL);
}

void oc_init_timer(Clock *clock)
{
    clock->interval = OC_BASE_INTERVAL;
    if (clock->tune == NULL)
        clock->tune = g_new0(TimeTuning, 1);
    clock->tune->level = 0;
    oc_start_timer(clock);
    oc_start_tuning(clock);
}

static void oc_update_size(Clock *clock, int size)
{
    /* keep in sync with systray */
    if (size > 26) {
        gtk_container_set_border_width(GTK_CONTAINER(clock->frame), 2);
        size -= 3;
    }
    else {
        gtk_container_set_border_width(GTK_CONTAINER(clock->frame), 0);
        size -= 1;
    }
}

static gboolean popup_program(GtkWidget *widget, gchar *program, Clock *clock
        , guint event_time)
{
    GdkAtom atom;
    Window xwindow;
    GError *error = NULL;
    GdkEventClient gev;
    gchar *check, *popup; /* atom names to use */

    if (strcmp(program, "orage") == 0) {
        check = "_XFCE_CALENDAR_RUNNING";
        popup = "_XFCE_CALENDAR_TOGGLE_HERE";
    }
    else if (strcmp(program, "globaltime") == 0) {
        check = "_XFCE_GLOBALTIME_RUNNING";
        popup = "_XFCE_GLOBALTIME_TOGGLE_HERE";
    }
    else {
        g_warning("unknown program to start %s", program);
        return(FALSE);
    }

    /* send message to program to check if it is running */
    atom = gdk_atom_intern(check, FALSE);
    if ((xwindow = XGetSelectionOwner(GDK_DISPLAY(),
            gdk_x11_atom_to_xatom(atom))) != None) { /* yes, then toggle */
        gev.type = GDK_CLIENT_EVENT;
        gev.window = widget->window;
        gev.send_event = TRUE;
        gev.message_type = gdk_atom_intern(popup, FALSE);
        gev.data_format = 8;

        if (!gdk_event_send_client_message((GdkEvent *) &gev,
                (GdkNativeWindow)xwindow)) 
             g_message("%s: send message to %s failed", OC_NAME, program);
        gdk_flush();

        return(TRUE);
    }
    else { /* not running, let's try to start it. Need to reset TZ! */
        static guint prev_event_time = 0; /* prevenst double start (BUG 4096) */

        if (prev_event_time && ((event_time - prev_event_time) < 1000)) {
            g_message("%s: double start of %s prevented", OC_NAME, program);
            return(FALSE);
        }
            
        prev_event_time = event_time;
        if (clock->TZ_orig != NULL)  /* we had TZ when we started */
            g_setenv("TZ", clock->TZ_orig, 1);
        else  /* TZ was not set so take it out */
            g_unsetenv("TZ");
        tzset();

        if (!xfce_exec(program, FALSE, FALSE, &error)) 
            g_message("%s: start of %s failed", OC_NAME, program);

        if ((clock->timezone->str != NULL) && (clock->timezone->len > 0)) {
        /* user has set timezone, so let's set TZ */
            g_setenv("TZ", clock->timezone->str, 1);
            tzset();
        }

        return(TRUE);
    }

    return(FALSE);
}

static gboolean on_button_press_event_cb(GtkWidget *widget
        , GdkEventButton *event, Clock *clock)
{
    if (event->type != GDK_BUTTON_PRESS) /* double or triple click */
        return(FALSE); /* ignore */
    if (event->button == 1)
        return(popup_program(widget, "orage", clock, event->time));
    else if (event->button == 2)
        return(popup_program(widget, "globaltime", clock, event->time));

    return(FALSE);
}


/* -------------------------------------------------------------------- *
 *                     Panel Plugin Interface                           *
 * -------------------------------------------------------------------- */


/* Interface Implementation */

static gboolean oc_set_size(XfcePanelPlugin *plugin, int size, Clock *clock)
{
    oc_update_size(clock, size);

    return(TRUE);
}

static void oc_free_data(XfcePanelPlugin *plugin, Clock *clock)
{
    GtkWidget *dlg = g_object_get_data(G_OBJECT(plugin), "dialog");

    if (dlg)
        gtk_widget_destroy(dlg);
    
    if (clock->timeout_id) {
        g_source_remove(clock->timeout_id);
    }
    g_object_unref(clock->tips);
    g_object_unref(clock->line[0].label);
    g_object_unref(clock->line[1].label);
    g_object_unref(clock->line[2].label);
    g_free(clock->TZ_orig);
    g_free(clock);
}

static void oc_read_rc_file(XfcePanelPlugin *plugin, Clock *clock)
{
    gchar  *file;
    XfceRc *rc;
    const gchar  *ret;
    gchar tmp[100];
    gint i;

    if (!(file = xfce_panel_plugin_lookup_rc_file(plugin)))
        return; /* if it does not exist, we use defaults from orage_oc_new */
    if (!(rc = xfce_rc_simple_open(file, TRUE))) {
        g_warning("unable to read-open rc file (%s)", file);
        return;
    }
    g_free(file);

    clock->show_frame = xfce_rc_read_bool_entry(rc, "show_frame", TRUE);

    clock->fg_set = xfce_rc_read_bool_entry(rc, "fg_set", FALSE);
    if (clock->fg_set) {
        ret = xfce_rc_read_entry(rc, "fg", NULL);
        sscanf(ret, "%uR %uG %uB"
                , (unsigned int *)&clock->fg.red
                , (unsigned int *)&clock->fg.green
                , (unsigned int *)&clock->fg.blue);
        clock->fg.pixel = 0;
    }

    clock->bg_set = xfce_rc_read_bool_entry(rc, "bg_set", FALSE);
    if (clock->bg_set) {
        ret = xfce_rc_read_entry(rc, "bg", NULL);
        sscanf(ret, "%uR %uG %uB"
                , (unsigned int *)&clock->bg.red
                , (unsigned int *)&clock->bg.green
                , (unsigned int *)&clock->bg.blue);
        clock->bg.pixel = 0;
    }

    ret = xfce_rc_read_entry(rc, "timezone", NULL);
    g_string_assign(clock->timezone, ret); 

    clock->width_set = xfce_rc_read_bool_entry(rc, "width_set", FALSE);
    if (clock->width_set) {
        clock->width = xfce_rc_read_int_entry(rc, "width", -1);
    }
    clock->height_set = xfce_rc_read_bool_entry(rc, "height_set", FALSE);
    if (clock->height_set) {
        clock->height = xfce_rc_read_int_entry(rc, "height", -1);
    }
    
    for (i = 0; i < OC_MAX_LINES; i++) {
        sprintf(tmp, "show%d", i);
        clock->line[i].show = xfce_rc_read_bool_entry(rc, tmp, FALSE);
        if (clock->line[i].show) {
            sprintf(tmp, "data%d", i);
            ret = xfce_rc_read_entry(rc, tmp, NULL);
            g_string_assign(clock->line[i].data, ret);

            sprintf(tmp, "font%d", i);
            ret = xfce_rc_read_entry(rc, tmp, NULL);
            g_string_assign(clock->line[i].font, ret);
        }
    }

    if (ret = xfce_rc_read_entry(rc, "tooltip", NULL))
        g_string_assign(clock->tooltip_data, ret); 

    xfce_rc_close(rc);
}

void oc_write_rc_file(XfcePanelPlugin *plugin, Clock *clock)
{
    gchar  *file;
    XfceRc *rc;
    gchar   tmp[100];
    gint i;

    if (!(file = xfce_panel_plugin_save_location(plugin, TRUE))) {
        g_warning("unable to write rc file");
        return;
    }
    if (!(rc = xfce_rc_simple_open(file, FALSE))) {
        g_warning("unable to read-open rc file (%s)", file);
        return;
    }
    g_free(file);

    xfce_rc_write_bool_entry(rc, "show_frame", clock->show_frame);

    xfce_rc_write_bool_entry(rc, "fg_set", clock->fg_set);
    if (clock->fg_set) {
        sprintf(tmp, "%uR %uG %uB"
                , clock->fg.red, clock->fg.green, clock->fg.blue);
        xfce_rc_write_entry(rc, "fg", tmp);
    }
    else {
        xfce_rc_delete_entry(rc, "fg", TRUE);
    }

    xfce_rc_write_bool_entry(rc, "bg_set", clock->bg_set);
    if (clock->bg_set) {
        sprintf(tmp, "%uR %uG %uB"
                , clock->bg.red, clock->bg.green, clock->bg.blue);
        xfce_rc_write_entry(rc, "bg", tmp);
    }
    else {
        xfce_rc_delete_entry(rc, "bg", TRUE);
    }

    xfce_rc_write_entry(rc, "timezone",  clock->timezone->str);

    xfce_rc_write_bool_entry(rc, "width_set", clock->width_set);
    if (clock->width_set) {
        xfce_rc_write_int_entry(rc, "width", clock->width);
    }
    else {
        xfce_rc_delete_entry(rc, "width", TRUE);
    }

    xfce_rc_write_bool_entry(rc, "height_set", clock->height_set);
    if (clock->height_set) {
        xfce_rc_write_int_entry(rc, "height", clock->height);
    }
    else {
        xfce_rc_delete_entry(rc, "height", TRUE);
    }

    for (i = 0; i < OC_MAX_LINES; i++) {
        sprintf(tmp, "show%d", i);
        xfce_rc_write_bool_entry(rc, tmp, clock->line[i].show);
        if (clock->line[i].show) {
            sprintf(tmp, "data%d", i);
            xfce_rc_write_entry(rc, tmp,  clock->line[i].data->str);
            sprintf(tmp, "font%d", i);
            xfce_rc_write_entry(rc, tmp,  clock->line[i].font->str);
        }
        else {
            sprintf(tmp, "data%d", i);
            xfce_rc_delete_entry(rc, tmp,  FALSE);
            sprintf(tmp, "font%d", i);
            xfce_rc_delete_entry(rc, tmp,  FALSE);
        }
    }

    xfce_rc_write_entry(rc, "tooltip",  clock->tooltip_data->str);

    xfce_rc_close(rc);
}

/* Create widgets and connect to signals */

Clock *orage_oc_new(XfcePanelPlugin *plugin)
{
    Clock *clock = g_new0(Clock, 1);
    gchar *data_init[] = {"%X", "%A", "%x"};
    gboolean show_init[] = {TRUE, FALSE, FALSE};
    gint  i;

    clock->plugin = plugin;

    clock->ebox = gtk_event_box_new();
    gtk_widget_show(clock->ebox);

    clock->frame = gtk_frame_new(NULL);
    gtk_container_add(GTK_CONTAINER(clock->ebox), clock->frame);
    gtk_widget_show(clock->frame);

    clock->vbox = gtk_vbox_new(TRUE, 0);
    gtk_widget_show(clock->vbox);
    gtk_container_add(GTK_CONTAINER(clock->frame), clock->vbox);

    clock->show_frame = TRUE;
    clock->fg_set = FALSE;
    clock->bg_set = FALSE;
    clock->width_set = FALSE;
    clock->height_set = FALSE;

    clock->timezone = g_string_new(""); /* = not set */
    clock->TZ_orig = g_strdup(g_getenv("TZ"));

    for (i = 0; i < OC_MAX_LINES; i++) {
        clock->line[i].label = gtk_label_new("");
        g_object_ref(clock->line[i].label); /* it is not always in the vbox */
        gtk_widget_show(clock->line[i].label);
        clock->line[i].show = show_init[i];
        clock->line[i].data = g_string_new(data_init[i]);
        clock->line[i].font = g_string_new("");
    }

    /* TRANSLATORS: Use format characters from strftime(3)
     * to get the proper string for your locale.
     * I used these:
     * %A  : full weekday name
     * %d  : day of the month
     * %B  : full month name
     * %Y  : four digit year
     * %V  : ISO week number
     */
    clock->tooltip_data = g_string_new(_("%A %d %B %Y/%V"));

    clock->tips = gtk_tooltips_new();
    g_object_ref(clock->tips);
    gtk_object_sink(GTK_OBJECT(clock->tips));
    oc_init_timer(clock);
        
    return(clock);
}

void oc_show_frame_set(Clock *clock)
{
    gtk_frame_set_shadow_type(GTK_FRAME(clock->frame)
            , clock->show_frame ? GTK_SHADOW_IN : GTK_SHADOW_NONE);
}

void oc_fg_set(Clock *clock)
{
    GdkColor *fg = NULL;
    gint      i;

    if (clock->fg_set)
        fg = &clock->fg;

    for (i = 0; i < OC_MAX_LINES; i++)
        gtk_widget_modify_fg(clock->line[i].label, GTK_STATE_NORMAL, fg);
}

void oc_bg_set(Clock *clock)
{
    GdkColor *bg = NULL;

    if (clock->bg_set)
        bg = &clock->bg;

    gtk_widget_modify_bg(clock->ebox, GTK_STATE_NORMAL, bg);
}

void oc_timezone_set(Clock *clock)
{
    if ((clock->timezone->str != NULL) && (clock->timezone->len > 0)) {
        /* user has set timezone, so let's set TZ */
        g_setenv("TZ", clock->timezone->str, 1);
    }
    else if (clock->TZ_orig != NULL) { /* we had TZ when we started */
        g_setenv("TZ", clock->TZ_orig, 1);
    }
    else { /* TZ was not set so take it out */
        g_unsetenv("TZ");
    }
    tzset();
}

void oc_size_set(Clock *clock)
{
    gint w, h;

    w = clock->width_set ? clock->width : -1;
    h = clock->height_set ? clock->height : -1;
    gtk_widget_set_size_request(clock->vbox, w, h);
}

void oc_show_line_set(Clock *clock, gint lno)
{
    GtkWidget *line_label = clock->line[lno].label;

    if (clock->line[lno].show) {
        gtk_box_pack_start(GTK_BOX(clock->vbox), line_label, FALSE, FALSE, 0);
        switch (lno) {
            case 0: /* always on top */
                gtk_box_reorder_child(GTK_BOX(clock->vbox), line_label, 0);
                break;
            case 1: /* if line 0 is missing, we are first */
                if (clock->line[0].show)  /* we are second line */
                    gtk_box_reorder_child(GTK_BOX(clock->vbox), line_label, 1);
                else /* we are top line */
                    gtk_box_reorder_child(GTK_BOX(clock->vbox), line_label, 0);
                break;
            case 2: /* always last */
                break;
        }
    }
    else {
        gtk_container_remove(GTK_CONTAINER(clock->vbox), line_label);
    }

    oc_update_size(clock,
            xfce_panel_plugin_get_size(XFCE_PANEL_PLUGIN(clock->plugin)));
}

void oc_line_font_set(Clock *clock, gint lno)
{
    PangoFontDescription *font;

    if (clock->line[lno].font->str) {
        font = pango_font_description_from_string(clock->line[lno].font->str);
        gtk_widget_modify_font(clock->line[lno].label, font);
        pango_font_description_free(font);
    }
    else
        gtk_widget_modify_font(clock->line[lno].label, NULL);
}

static void oc_construct(XfcePanelPlugin *plugin)
{
    Clock *clock;
    gint i;

    xfce_textdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");

    clock = orage_oc_new(plugin);

    gtk_container_add(GTK_CONTAINER(plugin), clock->ebox);

    oc_read_rc_file(plugin, clock);

    oc_show_frame_set(clock);
    oc_fg_set(clock);
    oc_bg_set(clock);
    oc_timezone_set(clock);
    oc_size_set(clock);
    for (i = 0; i < OC_MAX_LINES; i++) {
        if (clock->line[i].show)  /* need to add */
            oc_show_line_set(clock, i);
        oc_line_font_set(clock, i);
    }

    oc_update_size(clock, 
            xfce_panel_plugin_get_size(XFCE_PANEL_PLUGIN(plugin)));

    xfce_panel_plugin_add_action_widget(plugin, clock->ebox);
    
    xfce_panel_plugin_menu_show_configure(plugin);

    g_signal_connect(plugin, "configure-plugin", 
            G_CALLBACK(oc_properties_dialog), clock);

    g_signal_connect(plugin, "size-changed", 
            G_CALLBACK(oc_set_size), clock);
    
    g_signal_connect(plugin, "free-data", 
            G_CALLBACK(oc_free_data), clock);
    
    g_signal_connect(plugin, "save", 
            G_CALLBACK(oc_write_rc_file), clock);

/* callback for calendar and globaltime popup */
    g_signal_connect(clock->ebox, "button-press-event",
            G_CALLBACK(on_button_press_event_cb), clock);

}

/* Register with the panel */

XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL(oc_construct);