2006-08-31

GtkCellRendererToggle

#include <gtk/gtk.h>
#include <glib/gprintf.h>

static gboolean window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer data);
static void toggled_event( GtkWidget *widget, gchar *path, gpointer data);
static gboolean set_toggle( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
static void print_values( void);

GtkWidget *label;

char *numbers[] ={"Ichi", "Ni", "San", "Shi", "Go", "Roku", "Shichi", "Hachi", NULL};

enum
  {
    COL_TOGGLE,
    COL_DESC,
    N_COLUMNS
  };

GtkListStore *store;
GtkWidget *view;

gint selected =7;

int main( int argc, char **argv)
{
  GtkWidget *window, *vbox;
  GtkTreeViewColumn *column;
  GtkCellRenderer *renderer;
  GtkTreeIter iter;

  int i =0;

  gtk_set_locale( );

  gtk_init( &argc, &argv);

  window =gtk_window_new( GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title( GTK_WINDOW( window), "Toggle test");
  g_signal_connect( G_OBJECT( window),
      "delete_event",
      G_CALLBACK( window_delete_event), NULL);

  vbox =gtk_vbox_new( FALSE, 8);
  gtk_container_add( GTK_CONTAINER( window), vbox);

  label =gtk_label_new( "Choose one");
  gtk_box_pack_start( GTK_BOX( vbox), label, FALSE, TRUE, 8);

  store =gtk_list_store_new (N_COLUMNS,
         G_TYPE_BOOLEAN,
         G_TYPE_STRING);
  
  view =gtk_tree_view_new_with_model( GTK_TREE_MODEL( store));

  renderer =gtk_cell_renderer_toggle_new( );
  gtk_cell_renderer_toggle_set_radio( GTK_CELL_RENDERER_TOGGLE( renderer), TRUE);
  g_signal_connect( G_OBJECT( renderer),
      "toggled",
      G_CALLBACK( toggled_event), NULL);
  column =gtk_tree_view_column_new_with_attributes ("Default",
          renderer,
          "active", COL_TOGGLE,
          NULL);
  gtk_tree_view_append_column( GTK_TREE_VIEW( view), column); 

  renderer =gtk_cell_renderer_text_new( );
  column =gtk_tree_view_column_new_with_attributes( "Description", renderer,
          "text", COL_DESC,
          NULL);
  gtk_tree_view_append_column( GTK_TREE_VIEW( view), column); 

  while( NULL !=numbers[ i])
    {
      gtk_list_store_append( store, &iter);
      gtk_list_store_set( store, &iter,
     COL_TOGGLE, ( ( selected ==i) ? TRUE : FALSE),
     COL_DESC, numbers[ i++],
     -1);
    }

  gtk_box_pack_start( GTK_BOX( vbox), view, FALSE, TRUE, 8);

  gtk_widget_show_all( window);

  gtk_main( );

  return 0;
}

static gboolean window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer data)
{
  print_values( );

  exit( 0);
}

// I'm quite sure there is a better way...

static void toggled_event( GtkWidget *widget, gchar *path, gpointer data)
{
  GtkTreeIter iter;

  gtk_tree_model_foreach( GTK_TREE_MODEL( store), set_toggle, path);
 
  if( gtk_tree_model_get_iter_from_string( GTK_TREE_MODEL( store), &iter, path))
    {
      gtk_list_store_set( GTK_LIST_STORE( store), &iter, COL_TOGGLE, TRUE, -1);
    }
}

static gboolean set_toggle( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
  gtk_list_store_set( GTK_LIST_STORE( store), iter, COL_TOGGLE, FALSE, -1);

  return FALSE;
}

static void print_values( void)
{
  gboolean toggled;
  gchar *description;
  GtkTreeIter iter;

  if( gtk_tree_model_get_iter_first( GTK_TREE_MODEL( store), &iter))
    {
      while( TRUE)
 {
   gtk_tree_model_get( GTK_TREE_MODEL( store), &iter,
         COL_TOGGLE, &toggled,
         COL_DESC, &description,
         -1);

   g_printf( "%s %s (%p)\n", description, ( toggled ? "yes" : "no"), description);

   g_free( description);

   if( !gtk_tree_model_iter_next( GTK_TREE_MODEL( store), &iter))
     break;
 }
    }
}

2006-08-24

GThread & GAsyncQueue stuff

/*
  compile:
  gcc -Wall -g `pkg-config --cflags glib-2.0 gthread-2.0` main.c -o gthread-test `pkg-config --libs glib-2.0 gthread-2.0`
*/
#include <glib.h>
#include <glib/gprintf.h>

GAsyncQueue *qmsg, *qsig;

const glong sender_dly =G_USEC_PER_SEC/10;

gpointer sender( gpointer data);

int main( int argc, char **argv)
{
  GThread *s0, *s1;
  GTimeVal tv;
  GError *err =NULL;
  gint i;

  tv.tv_usec =G_USEC_PER_SEC/5;  // that's 200 ms

  if( !g_thread_supported( )) g_thread_init( NULL);

  qmsg =g_async_queue_new( );
  qsig =g_async_queue_new( );

  if( NULL ==(s0 =g_thread_create( (GThreadFunc)sender, NULL, TRUE, &err)))
    {
      g_printf( "s0 create fail: %s\n", err->message);
      return 1;
    }

  if( NULL ==(s1 =g_thread_create( (GThreadFunc)sender, NULL, TRUE, &err)))
    {
      g_printf( "s1 create fail: %s\n", err->message);
      return 1;
    }

  g_async_queue_ref( qmsg);
  g_async_queue_ref( qsig);

  for( i =0; i <100; i++)
    {
      g_printf( "%d\n", GPOINTER_TO_INT( g_async_queue_timed_pop( qmsg, &tv)));
    }

  g_async_queue_unref( qmsg);

  g_async_queue_push( qsig, GINT_TO_POINTER( 1));
  g_async_queue_push( qsig, GINT_TO_POINTER( 1));

  g_thread_join( s0);
  g_thread_join( s1);

  g_async_queue_unref( qsig);

  return 0;
}

gpointer sender( gpointer data)
{
  gpointer sig;
  gint niter =1;

  g_async_queue_ref( qmsg);
  g_async_queue_ref( qsig);

  while( NULL ==(sig =g_async_queue_try_pop( qsig)))
    {
      g_async_queue_push( qmsg, GINT_TO_POINTER( niter++));
      g_usleep( sender_dly);
    }

  g_async_queue_unref( qmsg);

  g_printf( "sender( ): received on qsig: %d (\"I'm outta here\")\n", GPOINTER_TO_INT( sig));

  g_async_queue_unref( qsig);

  return 0;
}

GList stuff

/*
  compile:
  gcc -Wall -g `pkg-config --cflags glib-2.0` main.c -o glist-test `pkg-config --libs glib-2.0`
*/

#include <glib.h>
#include <glib/gprintf.h>

void print_list( GList *list);
GList *free_elem( GList *list, gint data);

int main( int argc, char **argv)
{
  GList *list =NULL;
  gint i;

  for( i =1; i <8; i++)
    list =g_list_append( list, GINT_TO_POINTER( i));
  print_list( list);

  list =free_elem( list, 2);
  print_list( list);

  list =free_elem( list, 4);
  print_list( list);

  list =free_elem( list, 6);
  print_list( list);

  g_list_free( list);
  print_list( list);

  return 0;
}

void print_list( GList *list)
{
  GList *l;

  g_printf( "%p: ", list);

  for( l =list; l !=NULL; l =g_list_next( l))
    g_printf( "0x%x -> ", GPOINTER_TO_INT( l->data));
  g_printf( "NULL\n\n");
}

GList *free_elem( GList *list, gint data)
{
  GList *l =g_list_find( list, GINT_TO_POINTER( data));

  list =g_list_remove_link( list, g_list_find( list, GINT_TO_POINTER( data)));

  g_list_free_1( l);

  print_list( l);

  return list;
}
Running with:
valgrind --leak-check=yes --show-below-main=yes --show-reachable=yes ./glist-test
gives:
...

0x41df000: 0x1 -> 0x2 -> 0x3 -> 0x4 -> 0x5 -> 0x6 -> 0x7 -> NULL

0x41df010: 0x0 -> NULL

0x41df000: 0x1 -> 0x3 -> 0x4 -> 0x5 -> 0x6 -> 0x7 -> NULL

0x41df030: 0x41df010 -> NULL

0x41df000: 0x1 -> 0x3 -> 0x5 -> 0x6 -> 0x7 -> NULL

0x41df050: 0x41df030 -> NULL

0x41df000: 0x1 -> 0x3 -> 0x5 -> 0x7 -> NULL

0x41df000: 0x41df050 -> NULL

==5433== 
==5433== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
==5433== malloc/free: in use at exit: 4,556 bytes in 8 blocks.
==5433== malloc/free: 8 allocs, 0 frees, 4,556 bytes allocated.
==5433== For counts of detected errors, rerun with: -v
==5433== searching for pointers to 8 not-freed blocks.
==5433== checked 83,028 bytes.
==5433== 
==5433== 992 bytes in 4 blocks are still reachable in loss record 1 of 2
==5433==    at 0x401C970: memalign (vg_replace_malloc.c:332)
==5433==    by 0x401C9FB: posix_memalign (vg_replace_malloc.c:384)
==5433==    by 0x4063068: (within /usr/lib/libglib-2.0.so.0.1000.3)
==5433==    by 0x4063E20: g_slice_alloc (in /usr/lib/libglib-2.0.so.0.1000.3)
==5433==    by 0x404B8AB: g_list_append (in /usr/lib/libglib-2.0.so.0.1000.3)
==5433==    by 0x80484DD: main (main.c:21)
==5433==    by 0x40C2EA3: __libc_start_main (in /lib/tls/libc-2.3.6.so)
==5433==    by 0x8048420: ??? (start.S:119)
==5433== 
==5433== 
==5433== 3,564 bytes in 4 blocks are still reachable in loss record 2 of 2
==5433==    at 0x401C7AA: calloc (vg_replace_malloc.c:279)
==5433==    by 0x4054FC9: g_malloc0 (in /usr/lib/libglib-2.0.so.0.1000.3)
==5433==    by 0x4062CDF: (within /usr/lib/libglib-2.0.so.0.1000.3)
==5433==    by 0x4063C1E: g_slice_alloc (in /usr/lib/libglib-2.0.so.0.1000.3)
==5433==    by 0x404B8AB: g_list_append (in /usr/lib/libglib-2.0.so.0.1000.3)
==5433==    by 0x80484DD: main (main.c:21)
==5433==    by 0x40C2EA3: __libc_start_main (in /lib/tls/libc-2.3.6.so)
==5433==    by 0x8048420: ??? (start.S:119)
==5433== 
==5433== LEAK SUMMARY:
==5433==    definitely lost: 0 bytes in 0 blocks.
==5433==      possibly lost: 0 bytes in 0 blocks.
==5433==    still reachable: 4,556 bytes in 8 blocks.
==5433==         suppressed: 0 bytes in 0 blocks.
So free_elem( ) does it's job..? Gott weiß.

2006-08-19

pkg-config

CFLAGS_GTK = `pkg-config --cflags gtk+-2.0`
LIBS_GTK = `pkg-config --libs gtk+-2.0`

gcb-test: main.o
        $(CC) $(COMPILER_FLAGS) -o gcb-test main.o $(LIBS_GTK)

main.o: main.c
        $(CC) $(COMPILER_FLAGS) -c main.c -o main.o $(CFLAGS_GTK)

2006-08-18

(GCC) Inline assembly

Just for fun, M'am.
int main( int argc, char **argv)
{
  const char s[ ] ="Tread lightly\n", *p;

  write( 1, s, sizeof( s));

  // p =s;
  asm( "movl %1, %%eax; movl %%eax, %0;"
       :"=r" ( p)
       :"r" ( s)
       :"%eax"
       );

  while( *p)
    write( 1, p++, 1);

  return 0;
}

GtkComboBox stuff

#include <gtk/gtk.h>

static gboolean window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer data);
static void cbcb( GtkWidget *widget, gpointer data);

GtkWidget *label;

char *numbers[] ={"Ichi", "Ni", "San", "Shi", "Go", "Roku", "Shichi", "Hachi", NULL};

int main( int argc, char **argv)
{
  GtkWidget *window, *vbox, *combobox;
  int i =0;

  gtk_set_locale( );

  gtk_init( &argc, &argv);

  window =gtk_window_new( GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title( GTK_WINDOW( window), "The Walrus was Paul");
  g_signal_connect( G_OBJECT( window),
      "delete_event",
      G_CALLBACK( window_delete_event), NULL);

  vbox =gtk_vbox_new( FALSE, 8);
  gtk_container_add( GTK_CONTAINER( window), vbox);

  combobox =gtk_combo_box_new_text( );  // the easier way
  while( NULL !=numbers[ i])
    gtk_combo_box_append_text( GTK_COMBO_BOX( combobox), numbers[ i++]);
  g_signal_connect( combobox, "changed", G_CALLBACK( cbcb), NULL);
  gtk_box_pack_start( GTK_BOX( vbox), combobox, FALSE, TRUE, 8);

  label =gtk_label_new( "...");
  gtk_box_pack_start( GTK_BOX( vbox), label, FALSE, TRUE, 8);

  gtk_widget_show_all( window);

  gtk_main( );

  return 0;
}

static gboolean window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer data)
{
  exit( 0);
}

static void cbcb( GtkWidget *widget, gpointer data)
{
  gtk_label_set_text( GTK_LABEL( label),
        gtk_combo_box_get_active_text( GTK_COMBO_BOX( widget)));
}

GtkCheckButton stuff

main.c:
#include <gtk/gtk.h>

static gboolean window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer data);
static void cbcb( GtkWidget *widget, gpointer data);

GtkWidget *label;

char deny[] ="You live in denial!";
char admit[] ="That's right.";

int main( int argc, char **argv)
{
 GtkWidget *window, *vbox, *checkbutton;

 gtk_set_locale( );

 gtk_init( &argc, &argv);

 window =gtk_window_new( GTK_WINDOW_TOPLEVEL);
 gtk_window_set_title( GTK_WINDOW( window), "I am the Walrus");
 g_signal_connect( G_OBJECT( window),
     "delete_event",
     G_CALLBACK( window_delete_event), NULL);

 vbox =gtk_vbox_new( FALSE, 8);
 gtk_container_add( GTK_CONTAINER( window), vbox);

 checkbutton =gtk_check_button_new_with_label( "Soylent Green is made of people?");
 gtk_box_pack_start( GTK_BOX( vbox), checkbutton, FALSE, TRUE, 8);

 // "toggled" inherited from GtkToggleButton
 g_signal_connect( checkbutton, "toggled", G_CALLBACK( cbcb), NULL);

 label =gtk_label_new( deny);
 gtk_box_pack_start( GTK_BOX( vbox), label, FALSE, TRUE, 8);

 gtk_widget_show_all( window);

 gtk_main( );

 return 0;
}

static gboolean window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer data)
{
 exit( 0);
}

static void cbcb( GtkWidget *widget, gpointer data)
{
 if( FALSE ==gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget)))
   gtk_label_set_text( GTK_LABEL( label), deny);
 else
   gtk_label_set_text( GTK_LABEL( label), admit);
}

2006-08-03

Images flowing over bottom of container div

float: right; images don't add to height of the div they are in. So they flow over. To prevent this, add a <div id="clear_right"/>: #clear_right { clear: right; } after the images.