Listing 4: The implementation of the numeric keypad widget requires less than 150 lines of code

#include "gtk/gtktable.h"                          
#include "gtk/gtkbutton.h"                          
#include "gtk/gtklabel.h"                          
#include "numberpad.h"                          
                          
void numberpad_clicked(GtkWidget* widget, Numberpad* numberpad)                          
{                          
  if (widget == numberpad->enterButton)                          
  {                          
    if (strlen(numberpad->numbers) > 0)                          
    {                          
      int value = atoi(numberpad->numbers);                          
                               
      if (value >= numberpad->adjustment->lower &&                          
          value <= numberpad->adjustment->upper)                          
      {                          
        numberpad->adjustment->value = value;                          
                                  
        gtk_signal_emit_by_name(                          
          GTK_OBJECT(numberpad->adjustment), "value_changed");                          
      }                          
                                
      numberpad->numbers[0] = 0;                          
    }                          
  }                          
  else                          
  {                          
    int numbersLength = strlen(numberpad->numbers);                          
    gchar* label;                          
                              
    gtk_label_get(GTK_LABEL(GTK_BIN(widget)->child), &label);                          
                          
    if (numbersLength < 3)                          
    {                          
      numberpad->numbers[numbersLength] = label[0];                          
      numberpad->numbers[numbersLength+1] = 0;                          
    }                          
  }                          
}                          
                          
void numberpad_init(Numberpad* numberpad)                          
{                          
  GtkWidget* table;                          
  gint row, column, number, index;                          
                            
  table = gtk_table_new(3, 4, FALSE);                           
  gtk_container_add(GTK_CONTAINER(numberpad), table);                          
  gtk_widget_show(table);                          
                          
  // Add the buttons 1 through 9...                          
                            
  number = 1;                          
  for (row = 2; row >= 0; row--)                          
    for (column = 0; column < 3; column++)                          
    {                          
      unsigned char buffer[2];                          
      sprintf(buffer, "%i", number++);                          
                          
      index = row * 3 + column;                          
                          
      numberpad->numberButtons[index] =                          
        gtk_button_new_with_label(buffer);                          
                                
      gtk_table_attach_defaults(                          
        GTK_TABLE(table), numberpad->numberButtons[index],                          
        column, column+1, row, row+1);                          
                                
      gtk_signal_connect(                          
        GTK_OBJECT(numberpad->numberButtons[index]), "clicked",                          
        GTK_SIGNAL_FUNC(numberpad_clicked), numberpad);                          
                                
      gtk_widget_show(numberpad->numberButtons[index]);                          
    }                          
                             
  // Special case for adding the 0 button...                          
                           
  index = 9;                            
  numberpad->numberButtons[index] =                          
    gtk_button_new_with_label("0");                          
  gtk_table_attach_defaults(                          
    GTK_TABLE(table), numberpad->numberButtons[index],                          
    0, 1, 3, 4);                          
                           
  gtk_signal_connect(                          
    GTK_OBJECT(numberpad->numberButtons[index]), "clicked",                          
    GTK_SIGNAL_FUNC(numberpad_clicked), numberpad);                          
                           
    gtk_widget_show(numberpad->numberButtons[index]);                          
                          
  // And finally, add the Enterbutton...                          
                           
  numberpad->enterButton = gtk_button_new_with_label("Enter");                          
                           
  gtk_table_attach_defaults(                          
    GTK_TABLE(table), numberpad->enterButton,                          
    1, 3, 3, 4);                          
                           
  gtk_signal_connect(                          
    GTK_OBJECT(numberpad->enterButton), "clicked",                          
    GTK_SIGNAL_FUNC(numberpad_clicked), numberpad);                          
                           
  gtk_widget_show(numberpad->enterButton);                          
}                          
                          
guint numberpad_get_type()                          
{                          
  static guint numberpad_type = 0;                          
                          
  if (!numberpad_type)                          
  {                          
    GtkTypeInfo numberpad_info =                          
    {                          
      "Numberpad",                          
      sizeof(Numberpad),                          
      sizeof(GtkVBoxClass),                          
      NULL,                          
      (GtkObjectInitFunc) numberpad_init,                          
      NULL, NULL, NULL                          
    };                          
                          
    numberpad_type = gtk_type_unique(                          
      gtk_vbox_get_type(), &numberpad_info);                          
  }                          
                          
  return numberpad_type;                          
}                          
                          
GtkWidget* numberpad_new(GtkAdjustment* adjustment)                          
{                          
  Numberpad *numberpad;                          
                          
  numberpad = gtk_type_new(numberpad_get_type());                          
  numberpad->adjustment = adjustment;                          
  numberpad->numbers[0] = 0;                          
                           
  return GTK_WIDGET(numberpad);                          
}                          

s