Index: clock.c
===================================================================
--- clock.c	(revision 10921)
+++ clock.c	(working copy)
@@ -95,6 +95,7 @@
 	{ CLOCK_FORMAT_UNIX,     "unix"     },
 	{ CLOCK_FORMAT_INTERNET, "internet" },
 	{ CLOCK_FORMAT_CUSTOM,   "custom"   },
+        { CLOCK_FORMAT_FUZZY,    "fuzzy"    },
 	{ 0, NULL }
 };
 
@@ -238,6 +239,8 @@
 
 static void edit_hide (GtkWidget *unused, ClockData *cd);
 
+static void format_time_fuzzy (ClockData *cd, char hour[256], struct tm *tm);
+
 static void
 unfix_size (ClockData *cd)
 {
@@ -329,7 +332,7 @@
 		    (unsigned int)get_itime (cd->current_time)) {
 			update_clock (cd);
 		} else if ((cd->format == CLOCK_FORMAT_12 ||
-			    cd->format == CLOCK_FORMAT_24) &&
+			    cd->format == CLOCK_FORMAT_24 || cd->format == CLOCK_FORMAT_FUZZY) &&
 			   new_time / 60 != cd->current_time / 60) {
 			update_clock (cd);
 		}
@@ -419,8 +422,10 @@
 
 	if (cd->format == CLOCK_FORMAT_12)
 		time_format = cd->showseconds ? _("%l:%M:%S %p") : _("%l:%M %p");
-	else
+	else if (cd->format == CLOCK_FORMAT_24)
 		time_format = cd->showseconds ? _("%H:%M:%S") : _("%H:%M");
+        else if (cd->format == CLOCK_FORMAT_FUZZY)
+                time_format = _(""); /* fuzzy time rarely has same time_format */
 
 	if (!safe) {
 		/* FIXME: we need this for bug #410169 in pango. We'll be able
@@ -552,9 +557,22 @@
 		g_free (timeformat);
 
 		utf8 = g_locale_to_utf8 (hour, -1, NULL, NULL, NULL);
+        } else if (cd->format == CLOCK_FORMAT_FUZZY) {
+                /* Get the fuzzy time */
+                char time_piece[256];
+                char date_piece[256];
+                format_time_fuzzy(cd, time_piece, tm);
+                /* If the user wants date it will be added to date_piece */
+                if (strftime (date_piece, sizeof (date_piece), cd->timeformat, tm) <= 0)
+			strcpy (hour, "???");
+                /* Combine hour and time_piece to form whole thing */
+                if (strlen(time_piece) + strlen(date_piece) < 256) {
+                        g_snprintf(hour,256,"%s %s", date_piece,time_piece);
+                }
+                utf8 = g_locale_to_utf8 (hour, -1, NULL, NULL, NULL);
 	} else {
 		if (strftime (hour, sizeof (hour), cd->timeformat, tm) <= 0)
-			strcpy (hour, "???");
+			strcpy (hour, "???"); 
 
 		utf8 = g_locale_to_utf8 (hour, -1, NULL, NULL, NULL);
         }
@@ -565,6 +583,38 @@
         return utf8;
 }
 
+static void
+format_time_fuzzy(ClockData *cd, char hour[256], struct tm *tm)
+{
+        int hour_int = tm->tm_hour;
+        if (hour_int > 11)
+                hour_int -= 12;
+        int minute_int = tm->tm_min;
+        char* hour_names[] = {"twelve","one","two","three","four","five","six",
+                              "seven","eight","nine","ten","eleven","twelve","one"};
+        char* minute_names[] = {"o'clock","five","ten","quarter","twenty",
+                                "twenty five", "half"};
+        char *modifier[] = {"past","to"};
+        int modify_sector = 0;
+        /* normalize minute_int to be between 0 and 29 (basically split in half) */
+        if (minute_int > 30) {
+                minute_int -= 30;
+                modify_sector = 1;
+        }
+        /* we want to map minute_int to minute_names */
+        int sector = floor((minute_int+2) / 5 + .5);
+        if (modify_sector)
+                sector = 6 - sector;
+          
+        if (sector == 0)
+                g_snprintf(hour,256,"%s %s",hour_names[hour_int+modify_sector],minute_names[sector]);
+        else {
+                if (sector == 6 && modify_sector == 1)
+                        --modify_sector; /* to get half past hour */
+                g_snprintf(hour,256,"%s %s %s",minute_names[sector],modifier[modify_sector],hour_names[hour_int+modify_sector]);
+        }
+}
+
 static gchar *
 format_time_24 (ClockData *cd)
 {
@@ -664,21 +714,39 @@
                 g_free (utf8);
                 g_free (tip);
         } else {
+                GString *tooltip;
 #ifdef HAVE_LIBECAL
 		if (cd->calendar_popup)
-			gtk_widget_set_tooltip_text (cd->panel_button,
-						     _("Click to hide your appointments and tasks"));
+                        tooltip = g_string_new("Click to hide your appointments and tasks");
 		else
-			gtk_widget_set_tooltip_text (cd->panel_button,
-						     _("Click to view your appointments and tasks"));
+                        tooltip = g_string_new("Click to view your appointments and tasks");
 #else
 		if (cd->calendar_popup)
-			gtk_widget_set_tooltip_text (cd->panel_button,
-						     _("Click to hide month calendar"));
+                        tooltip = g_string_new("Click to hide month calendar");
 		else
-			gtk_widget_set_tooltip_text (cd->panel_button,
-						     _("Click to view month calendar"));
+                        tooltip = g_string_new("Click to view month calendar");
 #endif
+                if (cd->format == CLOCK_FORMAT_FUZZY) {
+                        /* Append real time to tooltip */
+                        struct tm *tm;
+                        char hour[256];
+                        char *utf8;
+                        
+                        utf8 = NULL;
+                        
+                        if (cd->gmt_time)
+                                tm = gmtime (&cd->current_time);
+                        else
+                                tm = localtime (&cd->current_time);
+                        if (strftime (hour, sizeof (hour), ", time is %l:%M %p", tm) <= 0)
+                                strcpy (hour, "???"); 
+                        
+                        utf8 = g_locale_to_utf8 (hour, -1, NULL, NULL, NULL);
+                        tooltip = g_string_append(tooltip,utf8);
+                        g_free (utf8);
+                }
+                gtk_widget_set_tooltip_text (cd->panel_button,tooltip->str);
+                g_string_free(tooltip, 1);
         }
 }
 
@@ -1558,12 +1626,18 @@
 			tm = gmtime (&cd->current_time);
 		else
 			tm = localtime (&cd->current_time);
+                
+                if (cd->format == CLOCK_FORMAT_FUZZY) {
+                        format_time_fuzzy(cd,string,tm);
+                }
 
-		if (!format)
-			strcpy (string, "???");
-		else if (strftime (string, sizeof (string), format, tm) <= 0)
-			strcpy (string, "???");
-		g_free (format);
+                if (cd->format != CLOCK_FORMAT_FUZZY) {
+                        if (!format)
+                                strcpy (string, "???");
+                        else if (strftime (string, sizeof (string), format, tm) <= 0)
+                                strcpy (string, "???");
+                }
+                g_free (format);
 	}
 
 	utf8 = g_locale_to_utf8 (string, -1, NULL, NULL, NULL);
@@ -2826,8 +2900,8 @@
 static void
 set_show_date_cb (GtkWidget *w,
 		  ClockData *clock)
-{
-	panel_applet_gconf_set_bool (PANEL_APPLET (clock->applet),
+{	
+        panel_applet_gconf_set_bool (PANEL_APPLET (clock->applet),
 				     KEY_SHOW_DATE,
 				     GTK_TOGGLE_BUTTON (w)->active,
 				     NULL);
@@ -3672,20 +3746,33 @@
 }
 
 static void
-set_12hr_format_radio_cb (GtkWidget *widget, ClockData *cd)
+set_clock_format_radio_cb (GtkWidget *widget, ClockData *cd)
 {
-	const gchar *val;
+        const gchar *val;
         ClockFormat format;
+        GtkWidget *radio_12hr;
+        GtkWidget *radio_24hr;
+	/* Get the radio widgets for comparison */
+        radio_12hr = glade_xml_get_widget (cd->glade_xml, "12hr_radio");
+        radio_24hr = glade_xml_get_widget (cd->glade_xml, "24hr_radio");
 
-	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
-                format = CLOCK_FORMAT_12;
-        else
-                format = CLOCK_FORMAT_24;
+        
+        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+                if (widget == radio_12hr)
+                        format = CLOCK_FORMAT_12;
+                else if (widget == radio_24hr)
+                        format = CLOCK_FORMAT_24;
+                else
+                        format = CLOCK_FORMAT_FUZZY;
 
-        val = gconf_enum_to_string (format_type_enum_map, format);
-
-	panel_applet_gconf_set_string (PANEL_APPLET (cd->applet),
-				       KEY_FORMAT, val, NULL);
+                /* This stays inside here because we receive 1 callback for toggling the new one
+                   and one callback for untoggling the old one */
+                val = gconf_enum_to_string (format_type_enum_map, format);
+                
+                panel_applet_gconf_set_string (PANEL_APPLET (cd->applet),
+                                               KEY_FORMAT, val, NULL);
+        }
+        
 }
 
 static void
@@ -3757,6 +3844,7 @@
 
         GtkWidget *radio_12hr;
         GtkWidget *radio_24hr;
+        GtkWidget *radio_fuzzy;
 	GtkWidget *widget;
 	GtkCellRenderer *renderer;
         GtkTreeViewColumn *col;
@@ -3766,16 +3854,23 @@
 	/* Set the 12 hour / 24 hour widget */
         radio_12hr = glade_xml_get_widget (cd->glade_xml, "12hr_radio");
         radio_24hr = glade_xml_get_widget (cd->glade_xml, "24hr_radio");
+        radio_fuzzy = glade_xml_get_widget (cd->glade_xml, "fuzzy_radio");
 
         if (cd->format == CLOCK_FORMAT_12)
                 widget = radio_12hr;
+        else if (cd->format == CLOCK_FORMAT_24)
+                widget = radio_24hr;
         else
-                widget = radio_24hr;
+                widget = radio_fuzzy;
 
         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
 
 	g_signal_connect (radio_12hr, "toggled",
-			  G_CALLBACK (set_12hr_format_radio_cb), cd);
+			  G_CALLBACK (set_clock_format_radio_cb), cd);
+        g_signal_connect (radio_fuzzy, "toggled",
+                          G_CALLBACK (set_clock_format_radio_cb), cd);
+        g_signal_connect (radio_24hr, "toggled",
+                          G_CALLBACK (set_clock_format_radio_cb), cd);
 
 	/* Set the "Show Date" checkbox */
 	widget = glade_xml_get_widget (cd->glade_xml, "date_check");
Index: clock-utils.h
===================================================================
--- clock-utils.h	(revision 10921)
+++ clock-utils.h	(working copy)
@@ -38,7 +38,8 @@
 	CLOCK_FORMAT_24,
 	CLOCK_FORMAT_UNIX,
 	CLOCK_FORMAT_INTERNET,
-	CLOCK_FORMAT_CUSTOM
+	CLOCK_FORMAT_CUSTOM,
+	CLOCK_FORMAT_FUZZY
 } ClockFormat;
 
 ClockFormat clock_locale_format (void);
Index: clock.glade
===================================================================
--- clock.glade	(revision 10921)
+++ clock.glade	(working copy)
@@ -1230,6 +1230,26 @@
 			      <property name="fill">False</property>
 			    </packing>
 			  </child>
+
+			  <child>
+			    <widget class="GtkRadioButton" id="fuzzy_radio">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="label" translatable="yes">_fuzzy format</property>
+			      <property name="use_underline">True</property>
+			      <property name="relief">GTK_RELIEF_NORMAL</property>
+			      <property name="focus_on_click">True</property>
+			      <property name="active">False</property>
+			      <property name="inconsistent">False</property>
+			      <property name="draw_indicator">True</property>
+			      <property name="group">12hr_radio</property>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">False</property>
+			      <property name="fill">False</property>
+			    </packing>
+			  </child>
 			</widget>
 		      </child>
 		    </widget>
