? Keyboard.kbd
? am
? automatic-scanning.xam
? az
? be
? ca
? cs
? cy
? da
? de
? direct-selection.xam
? dwell-selection.xam
? el
? es
? fr
? gok-0.9.3.tar.gz
? gok-output-strip.diff
? gok-performance-patch-1.diff
? gok-strstrip.diff
? gok.desktop
? hi
? hr
? inverse-scanning.xam
? it
? ja
? ko
? mk
? ml
? ms
? nl
? no
? performance.txt
? pl
? pt
? pt_BR
? sk
? sl
? sq
? sr
? sr@Latn
? sv
? ta
? talking-gok.diff
? talking-gok.patch
? uk
? vi
? zh_CN
? zh_TW
? docs/reference/gok-decl-list.txt
? docs/reference/gok-decl.txt
? docs/reference/gok-undocumented.txt
? docs/reference/gok-unused.txt
? docs/reference/gok.args
? docs/reference/gok.hierarchy
? docs/reference/gok.signals
? docs/reference/html
? docs/reference/html-build.stamp
? docs/reference/html.stamp
? docs/reference/scan-build.stamp
? docs/reference/sgml
? docs/reference/sgml-build.stamp
? docs/reference/sgml.stamp
? docs/reference/tmpl-build.stamp
? docs/reference/tmpl.stamp
? gok/keyboard-geometry
? gok/test-focus-reject
? gok/test-gok-wordcomplete
Index: gok/gok-data.c
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-data.c,v
retrieving revision 1.42
diff -u -r1.42 gok-data.c
--- gok/gok-data.c	10 Nov 2003 21:17:56 -0000	1.42
+++ gok/gok-data.c	28 Nov 2003 14:41:30 -0000
@@ -1229,7 +1229,7 @@
  *
  */
 void
-gok_data_set_aux_dictionaries (const gchar *dictionaries)
+gok_data_set_aux_dictionaries (gchar *dictionaries)
 {
 	m_AuxDicts = dictionaries;
 	gok_gconf_set_string (gconf_client, GOK_GCONF_AUX_DICTS,
Index: gok/gok-data.h
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-data.h,v
retrieving revision 1.25
diff -u -r1.25 gok-data.h
--- gok/gok-data.h	4 Nov 2003 13:40:12 -0000	1.25
+++ gok/gok-data.h	28 Nov 2003 14:41:30 -0000
@@ -120,7 +120,7 @@
 void gok_data_set_repeat_rate (gint rate);
 GConfClient* gok_data_get_gconf_client (void);
 const gchar* gok_data_get_aux_dictionaries (void);
-void gok_data_set_aux_dictionaries (const gchar *dictionaries);
+void gok_data_set_aux_dictionaries (gchar *dictionaries);
 gboolean gok_data_get_use_aux_dictionaries (void);
 void gok_data_set_use_aux_dictionaries (gboolean use_aux);
 
Index: gok/gok-key.c
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-key.c,v
retrieving revision 1.78
diff -u -r1.78 gok-key.c
--- gok/gok-key.c	17 Nov 2003 17:35:00 -0000	1.78
+++ gok/gok-key.c	28 Nov 2003 14:41:30 -0000
@@ -248,8 +248,17 @@
   }
   else {  /* try again, without modifiers...*/
 	  nbytes = MIN (XkbTranslateKeySym (display, &keysym, 0, buf, 19, &extra_rtn), 19);
-	  return gok_key_label_from_keysym_string (
-		  (nbytes && g_unichar_isgraph (g_utf8_get_char_validated (buf, nbytes))) ? buf : XKeysymToString (keysym));
+	  if (nbytes) fprintf (stderr, "XkbTranslateKeysym:%s\n", buf);
+	  if (nbytes && g_unichar_isgraph (g_utf8_get_char_validated (buf, nbytes)))
+	  {
+		  return gok_key_label_from_keysym_string (buf);
+	  }
+	  else 
+	  {
+		  gchar *s = XKeysymToString (keysym);
+		  fprintf (stderr, "falling back to XKeysymToString: %s.\n", s);
+		  return gok_key_label_from_keysym_string (XKeysymToString (keysym));
+	  }
   }
 }
 
@@ -521,7 +530,7 @@
 	pgok_key_new->pMimicKey = NULL;
 	pgok_key_new->pKeyNext = pKeyNext;
 	pgok_key_new->pKeyPrevious = pKeyPrevious;
-	pgok_key_new->pNodeAccessible = NULL;
+	pgok_key_new->accessible_node = NULL;
 	pgok_key_new->FontSizeGroup = FONT_SIZE_GROUP_UNDEFINED;
 	pgok_key_new->FontSize = -1; /* not set yet */
 	pgok_key_new->ComponentState.active = 0;
@@ -598,6 +607,7 @@
 
 	/* delete all the key's labels */
 	pLabel = pKey->pLabel;
+	fprintf (stderr, "deleting key %s\n", pLabel->Text ? pLabel->Text : "<empty>");
 	while (pLabel != NULL)
 	{
 		pLabelTemp = pLabel;
@@ -624,6 +634,14 @@
 	gok_output_delete_all (pKey->pOutput);
 	gok_output_delete_all (pKey->pOutputWrapperPre);
 	gok_output_delete_all (pKey->pOutputWrapperPost);
+
+	if (pKey->accessible_node && pKey->accessible_node->paccessible) 
+	{
+		fprintf (stderr, "unreffing\n");
+/*		gok_spy_accessible_unref (pKey->accessible_node->paccessible);
+		pKey->accessible_node = NULL; */
+/* null this because there seems to be a bug causing keys to be deleted more than once :-( */
+	} 
 
 	g_free (pKey);
 
Index: gok/gok-key.h
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-key.h,v
retrieving revision 1.50
diff -u -r1.50 gok-key.h
--- gok/gok-key.h	4 Nov 2003 13:40:12 -0000	1.50
+++ gok/gok-key.h	28 Nov 2003 14:41:30 -0000
@@ -190,7 +190,7 @@
 	guint has_image:1;
 	guint is_repeatable:1;
         guint unused:13; /* nicer alignment in case compiler is weird */
-	AccessibleNode* pNodeAccessible;
+	AccessibleNode* accessible_node;
 	gint CellsRequired;
 	gint FontSizeGroup;
 	gint FontSize;
Index: gok/gok-keyboard.c
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-keyboard.c,v
retrieving revision 1.109
diff -u -r1.109 gok-keyboard.c
--- gok/gok-keyboard.c	19 Nov 2003 19:15:42 -0000	1.109
+++ gok/gok-keyboard.c	28 Nov 2003 14:41:31 -0000
@@ -951,9 +951,6 @@
 
 	gok_log("deleting keyboard: %s",pKeyboard->Name);
 	
-	/* delete the AccessibleNode list */
-	gok_spy_free(pKeyboard->pNodeAccessible);
-
 	if (pKeyboard->pAccessible != NULL)
 	{
 		gok_spy_accessible_unref(pKeyboard->pAccessible);
@@ -1037,8 +1034,6 @@
 	pGokKeyboardNew->bCommandPredictionKeysAdded = FALSE;
 	pGokKeyboardNew->expand = GOK_EXPAND_SOMETIMES;
 	pGokKeyboardNew->pAccessible = NULL;	
-	pGokKeyboardNew->pNodeAccessible = NULL;	
-	pGokKeyboardNew->search_role = SPI_ROLE_MENU;
 	
 	m_NumberOfKeyboards++;
 	
@@ -1901,47 +1896,48 @@
 			break;
 
 		case KEYTYPE_BRANCHMENUS:
-			gok_log("branch back SPI_ROLE_MENU");		
-			return gok_keyboard_branch_gui(pKey->pNodeAccessible, 
-						       GOK_SPY_SEARCH_MENU,
-						       SPI_ROLE_MENU); 
+			gok_log("branch gui MENUS");		
+			fprintf (stderr, "branch gui (MENUS)\n");
+			return gok_keyboard_branch_gui (pKey->accessible_node, 
+							GOK_SPY_SEARCH_MENU);
 			break;
 
 		case KEYTYPE_BRANCHMENUITEMS:
-			gok_log("branch gui SPI_ROLE_MENU_ITEM");		
-			return gok_keyboard_branch_gui(pKey->pNodeAccessible, 
-						       GOK_SPY_SEARCH_MENU, 
-						       /* does this work for check menu items too? */
-						       SPI_ROLE_MENU_ITEM);
+			gok_log("branch gui MENUS");
+			fprintf (stderr, "branch gui (MENUITEMS)\n");
+			return gok_keyboard_branch_gui (pKey->accessible_node, 
+							GOK_SPY_SEARCH_CHILDREN);
 			break;
 			
 		case KEYTYPE_BRANCHTOOLBARS:
-			gok_log("branch gui SPI_ROLE_PUSH_BUTTON");		
-			return gok_keyboard_branch_gui(pKey->pNodeAccessible, 
-						       GOK_SPY_SEARCH_ROLE,
-						       SPI_ROLE_PUSH_BUTTON); 
+			gok_log("branch gui TOOLBAR");		
+			return gok_keyboard_branch_gui (pKey->accessible_node, 
+							GOK_SPY_SEARCH_TOOLBARS);
 			break;
+
 		case KEYTYPE_BRANCHGUI:
 			gok_log("branch gui SPI_ROLE_PUSH_BUTTON");		
-			return gok_keyboard_branch_gui(pKey->pNodeAccessible, 
-						       GOK_SPY_SEARCH_UI,
-						       SPI_ROLE_PUSH_BUTTON); 
+			return gok_keyboard_branch_gui (pKey->accessible_node, 
+							GOK_SPY_SEARCH_UI);
 			break;			
 		case KEYTYPE_PAGESELECTION:
 			gok_log("page select");
-			gok_keyboard_page_select (pKey->pNodeAccessible);
+			gok_keyboard_page_select (pKey->accessible_node);
 			return FALSE;
 			break;
 		case KEYTYPE_BRANCHGUIACTIONS:
 			gok_log("branch gui_actions");
-			is_branched = gok_keyboard_branch_gui_actions(pKey->pNodeAccessible);
+			is_branched = gok_keyboard_branch_gui_actions (pKey->accessible_node);
 			if (!is_branched) 
 			{
-				pStateSet = Accessible_getStateSet (pKey->pNodeAccessible->paccessible);
-				is_active = AccessibleStateSet_contains (pStateSet, 
-									 SPI_STATE_CHECKED);
-				pKey->ComponentState.active = is_active;
-				AccessibleStateSet_unref (pStateSet);
+				if (pKey->accessible_node)
+				{	
+					pStateSet = Accessible_getStateSet (pKey->accessible_node->paccessible);
+					is_active = AccessibleStateSet_contains (pStateSet, 
+										 SPI_STATE_CHECKED);
+					pKey->ComponentState.active = is_active;
+					AccessibleStateSet_unref (pStateSet);
+				}
 			}
 			return is_branched;
 			break;
@@ -1978,7 +1974,7 @@
 gok_keyboard_update_dynamic (GokKeyboard* pKeyboard)
 {
 	AccessibleNode* pNodeAccessible;
-	AccessibleNode* pNodeAccessibleNext;
+	GSList *nodes;
 	AccessibleStateSet *pStateSet;
 	GokKey* pKey;
 	GokKey* pKeyTemp;
@@ -1996,13 +1992,6 @@
 		return FALSE;
 	}
 
-	/* delete the AccessibleNode list if one exists */
-	if (pKeyboard->pNodeAccessible != NULL)
-	{
-		gok_spy_free(pKeyboard->pNodeAccessible);
-		pKeyboard->pNodeAccessible = NULL;
-	}
-	
 	/* delete any keys that are currently on the keyboard */
 	pKey = pKeyboard->pKeyFirst;
 	while (pKey != NULL)
@@ -2015,31 +2004,34 @@
 
 	
 #if REINSTATE_APPLICATIONS
-	if (pKeyboard->search_role == GOKSPY_ROLE_APPLICATION)
+	if (pKeyboard->search_type == SEARCH_TYPE_APPLICATION)
 	{
 		pNodeAccessible = gok_spy_get_applications();
 	}
 	else
 	{
 #endif
-	gok_log("calling get list with accessible [%#x] and role [%s]", 
-		pKeyboard->pAccessible, AccessibleRole_getName(pKeyboard->search_role));
-	/* create new keys for the keyboard */
+	gok_log("calling get list with accessible [%#x]", pKeyboard->pAccessible);
 
+	/* create new keys for the keyboard */
+	switch (pKeyboard->search_type)
+	{
+	case GOK_SPY_SEARCH_CHILDREN:
+		nodes = gok_spy_get_children (pKeyboard->pAccessible);
+		break;
+	default:
+		nodes =	gok_spy_get_list (pKeyboard->pAccessible);
+		break;
+	}
 
-	/* TODO: REFACTOR: enum KeyType (keyboard role) */
-	pNodeAccessible = 
-		gok_spy_get_list (pKeyboard->pAccessible, pKeyboard->search_type, pKeyboard->search_role);
-		
-	if (pNodeAccessible == NULL)
+	if (nodes == NULL)
 	{
-		gok_log_x ("Warning: pNodeAccessible is NULL!");
+		gok_log_x ("Warning: no nodes found!");
 		gok_log_leave();
 		return FALSE;
 	}
 	
-	/* store the list head on the keyboard so that it can be deallocated later */
-	pKeyboard->pNodeAccessible = pNodeAccessible;
+	pNodeAccessible = nodes->data;
 	
 	/* add the new keys to the dynamic keyboard */
 	/* first, add a 'back' key */
@@ -2059,120 +2051,126 @@
 	pKeyboard->bLaidOut = FALSE;
 
 	column = 1;
-	pNodeAccessibleNext = pNodeAccessible;
 
-	while (pNodeAccessibleNext != NULL)
+	while (nodes)
 	{
-		pKey = gok_key_new (pKeyPrevious, NULL, pKeyboard);
-		pKeyPrevious = pKey;
-		
-		pKey->Style = KEYSTYLE_GENERALDYNAMIC;
-		
-		gok_log("node has role: [%s]",Accessible_getRoleName(pNodeAccessibleNext->paccessible));
-		
-		pStateSet = Accessible_getStateSet (pNodeAccessibleNext->paccessible);
-		switch (Accessible_getRole(pNodeAccessibleNext->paccessible))
-		{
-			/*
-			  case SPI_ROLE_INVALID:
-			  gok_log_x("invalid role in accessible node list!");
-			  pKey->Type = KEYTYPE_NORMAL;
-			  break;
-			*/
-		case SPI_ROLE_MENU:
-			gok_log("setting key type BRANCHMENUITEMS");
-			pKey->Type = KEYTYPE_BRANCHMENUITEMS;
-			pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_BRANCHMENUITEMS);
-			break;
-			/* add cases here	
-			   case SPI_ROLE_XXX:
-			   pKey->Type = KEYTYPE_BRANCHXXX;
-			   break;
-			*/
-		case SPI_ROLE_CHECK_BOX:
-		case SPI_ROLE_CHECK_MENU_ITEM:
-		case SPI_ROLE_TOGGLE_BUTTON:
-			pKey->Type = KEYTYPE_BRANCHGUIACTIONS;
-			pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_BRANCHGUIACTIONS);
-			pKey->has_image = TRUE;
-			pKey->pImage = gok_keyimage_new (pKey, NULL);
-			pKey->pImage->type = IMAGE_TYPE_INDICATOR;
-			is_active = AccessibleStateSet_contains (pStateSet, 
-								 SPI_STATE_CHECKED);
-			pKey->ComponentState.active = is_active;
-			break;
-		case SPI_ROLE_RADIO_BUTTON:
-		case SPI_ROLE_RADIO_MENU_ITEM:
-			pKey->Type = KEYTYPE_BRANCHGUIACTIONS;
-			pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_BRANCHGUIACTIONS);
-			pKey->has_image = TRUE;
-			pKey->pImage = gok_keyimage_new (pKey, NULL);
-			pKey->pImage->type = IMAGE_TYPE_INDICATOR;
-			is_active = AccessibleStateSet_contains (pStateSet, 
-								 SPI_STATE_CHECKED);
-			pKey->ComponentState.active = is_active;
-			pKey->ComponentState.radio = TRUE;
-			break;
-		case SPI_ROLE_PAGE_TAB:
-			/* no action implemented,, must use selection API on parent */
-			pKey->Type = KEYTYPE_PAGESELECTION;
-			pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_PAGESELECTION);
-			break;
-		case SPI_ROLE_TEXT:
-			/* should only be in the list if it's editable...*/
-			if (pNodeAccessibleNext->is_link) {
-			      pKey->Type = KEYTYPE_HYPERLINK;
-			      pKey->Style = KEYSTYLE_HYPERLINK;
-			      is_active = FALSE;
-			}
-			else {
-			      pKey->Type = KEYTYPE_BRANCHTEXT;
-			      if (AccessibleStateSet_contains (pStateSet, SPI_STATE_EDITABLE)) { 
-				      pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_BRANCHTEXT);
-				      is_active = TRUE;
-			      }
-			      else {
-				      is_active = FALSE;
-				      pKey->Style = KEYSTYLE_INSENSITIVE;
-			      }
-			}
-			pKey->ComponentState.active = is_active;
-			break;
-		case SPI_ROLE_HTML_CONTAINER: /* TODO: check Hypertext interface instead */
-			pKey->Type = KEYTYPE_BRANCHHYPERTEXT;
-			pKey->Style = KEYSTYLE_BRANCH; /* reuse 'normal' branch style for now. */
-			is_active = AccessibleStateSet_contains (pStateSet, 
-								 SPI_STATE_SENSITIVE);
-			pKey->ComponentState.active = is_active;
-			break;
-		default:
-			if (Accessible_isHypertext (pNodeAccessibleNext->paccessible)) {
-				pKey->Type = KEYTYPE_BRANCHHYPERTEXT;
-				pKey->Style = KEYSTYLE_BRANCH; /* reuse 'normal' branch style for now. */
-				is_active = TRUE; /* FIXME, might not be enabled? */
+	        pNodeAccessible = nodes->data;
+		if (gok_spy_node_match (pNodeAccessible, pKeyboard->search_type)) {
+			pKey = gok_key_new (pKeyPrevious, NULL, pKeyboard);
+			pKeyPrevious = pKey;
+			
+			pKey->Style = KEYSTYLE_GENERALDYNAMIC;
+			
+			gok_log("node has role: [%s]",Accessible_getRoleName(pNodeAccessible->paccessible));
+
+			fprintf (stderr, "%s: %s\n", Accessible_getRoleName (pNodeAccessible->paccessible), 
+				 Accessible_getName (pNodeAccessible->paccessible));
+			
+			pStateSet = Accessible_getStateSet (pNodeAccessible->paccessible);
+			switch (Accessible_getRole(pNodeAccessible->paccessible))
+			{
+				/*
+				  case SPI_ROLE_INVALID:
+				  gok_log_x("invalid role in accessible node list!");
+				  pKey->Type = KEYTYPE_NORMAL;
+				  break;
+				*/
+			case SPI_ROLE_MENU:
+				gok_log("setting key type BRANCHMENUITEMS");
+				fprintf (stderr, "key type menus created\n");
+				pKey->Type = KEYTYPE_BRANCHMENUITEMS;
+				pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_BRANCHMENUS);
+				break;
+				/* add cases here	
+				   case SPI_ROLE_XXX:
+				   pKey->Type = KEYTYPE_BRANCHXXX;
+				   break;
+				*/
+			case SPI_ROLE_CHECK_BOX:
+			case SPI_ROLE_CHECK_MENU_ITEM:
+			case SPI_ROLE_TOGGLE_BUTTON:
+				pKey->Type = KEYTYPE_BRANCHGUIACTIONS;
+				pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_BRANCHGUIACTIONS);
+				pKey->has_image = TRUE;
+				pKey->pImage = gok_keyimage_new (pKey, NULL);
+				pKey->pImage->type = IMAGE_TYPE_INDICATOR;
+				is_active = AccessibleStateSet_contains (pStateSet, 
+									 SPI_STATE_CHECKED);
 				pKey->ComponentState.active = is_active;
-			}
-			else {
-				/* this might be a dangerous catch all... */
-				gok_log("setting key type BRANCHGUIACTIONS");
+				break;
+			case SPI_ROLE_RADIO_BUTTON:
+			case SPI_ROLE_RADIO_MENU_ITEM:
 				pKey->Type = KEYTYPE_BRANCHGUIACTIONS;
 				pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_BRANCHGUIACTIONS);
+				pKey->has_image = TRUE;
+				pKey->pImage = gok_keyimage_new (pKey, NULL);
+				pKey->pImage->type = IMAGE_TYPE_INDICATOR;
+				is_active = AccessibleStateSet_contains (pStateSet, 
+									 SPI_STATE_CHECKED);
+				pKey->ComponentState.active = is_active;
+				pKey->ComponentState.radio = TRUE;
+				break;
+			case SPI_ROLE_PAGE_TAB:
+				/* no action implemented,, must use selection API on parent */
+				pKey->Type = KEYTYPE_PAGESELECTION;
+				pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_PAGESELECTION);
+				break;
+			case SPI_ROLE_TEXT:
+				/* should only be in the list if it's editable...*/
+				if (pNodeAccessible->flags.is_link) {
+					pKey->Type = KEYTYPE_HYPERLINK;
+					pKey->Style = KEYSTYLE_HYPERLINK;
+					is_active = FALSE;
+				}
+				else {
+					pKey->Type = KEYTYPE_BRANCHTEXT;
+					if (AccessibleStateSet_contains (pStateSet, SPI_STATE_EDITABLE)) { 
+						pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_BRANCHTEXT);
+						is_active = TRUE;
+					}
+					else {
+						is_active = FALSE;
+						pKey->Style = KEYSTYLE_INSENSITIVE;
+					}
+				}
+				pKey->ComponentState.active = is_active;
+				break;
+			case SPI_ROLE_HTML_CONTAINER: /* TODO: check Hypertext interface instead */
+				pKey->Type = KEYTYPE_BRANCHHYPERTEXT;
+				pKey->Style = KEYSTYLE_BRANCH; /* reuse 'normal' branch style for now. */
+				is_active = AccessibleStateSet_contains (pStateSet, 
+									 SPI_STATE_SENSITIVE);
+				pKey->ComponentState.active = is_active;
+				break;
+			default:
+				if (Accessible_isHypertext (pNodeAccessible->paccessible)) {
+					pKey->Type = KEYTYPE_BRANCHHYPERTEXT;
+					pKey->Style = KEYSTYLE_BRANCH; /* reuse 'normal' branch style for now. */
+					is_active = TRUE; /* FIXME, might not be enabled? */
+					pKey->ComponentState.active = is_active;
+				}
+				else {
+					/* this might be a dangerous catch all... */
+					gok_log("setting key type BRANCHGUIACTIONS");
+					pKey->Type = KEYTYPE_BRANCHGUIACTIONS;
+					pKey->Style = gok_style_if_enabled (pStateSet, KEYSTYLE_BRANCHGUIACTIONS);
+				}
+				break;
 			}
-			break;
+			AccessibleStateSet_unref (pStateSet);
+			pKey->Top = 0;
+			pKey->Bottom = 1;
+			pKey->Left = column;
+			pKey->Right = column + 1;
+			gok_spy_accessible_ref (pNodeAccessible->paccessible);
+			pKey->accessible_node = pNodeAccessible;
+			
+			gok_log("adding label %s to dynamic key",pNodeAccessible->pname);
+			gok_key_add_label (pKey, pNodeAccessible->pname, 0, 0);
+			
+			column++;
 		}
-
-		AccessibleStateSet_unref (pStateSet);
-		pKey->Top = 0;
-		pKey->Bottom = 1;
-		pKey->Left = column;
-		pKey->Right = column + 1;
-		pKey->pNodeAccessible = pNodeAccessibleNext;
-		
-		gok_log("adding label %s to dynamic key",pNodeAccessibleNext->pname);
-		gok_key_add_label (pKey, pNodeAccessibleNext->pname, 0, 0);
-		
-		column++;
-		pNodeAccessibleNext = pNodeAccessibleNext->pnext;
+		nodes = g_slist_next (nodes);
 	}	
 
 	gok_log_leave();
@@ -2183,22 +2181,21 @@
 * gok_keyboard_branch_gui
 * @pNodeAccessible: Pointer to the accessible node (parent object).
 * @type: Type of dynamic keyboard to branch to (the role of the children).
-* @role: role to match, if type is #GOK_SPY_SEARCH_ROLE.
 *
 * Displays the generic gui keyboard - currently used for widgets inside windowish things
 *
 * Returns: TRUE if the keyboard was displayed, FALSE if not.
 **/
 gboolean 
-gok_keyboard_branch_gui (AccessibleNode* pNodeAccessible, 
-				  GokSpySearchType type, AccessibleRole role)
+gok_keyboard_branch_gui (AccessibleNode *pNodeAccessible, 
+			 GokSpySearchType type)
 {
 	Accessible* pAccessibleRoot;
 	GokKeyboard* pKeyboard;
 	GokKeyboard* pKeyboardTemp;
 
 	gok_log_enter();
-	
+
 	pAccessibleRoot = NULL;
 
 	if (pNodeAccessible != NULL)
@@ -2245,7 +2242,6 @@
 	pKeyboardTemp->pKeyboardNext = pKeyboard;
 	pKeyboard->pKeyboardPrevious = pKeyboardTemp;
 	pKeyboard->search_type = type;
-	pKeyboard->search_role = role;
 
 	/* set the name and type of the keyboard */
 	switch (type)
@@ -2254,10 +2250,9 @@
 		pKeyboard->Type = KEYBOARD_TYPE_GUI;
 		gok_keyboard_set_name (pKeyboard, _("GUI"));
 		break;
-	case GOK_SPY_SEARCH_ROLE:
-		pKeyboard->Type = KEYBOARD_TYPE_TOOLBAR; /* catch-all ok ? */
-		/* TODO: localize the return value from AccessibleRole_getName */
-		gok_keyboard_set_name (pKeyboard, AccessibleRole_getName (role));
+	case GOK_SPY_SEARCH_TOOLBARS:
+		pKeyboard->Type = KEYBOARD_TYPE_TOOLBAR; 
+		gok_keyboard_set_name (pKeyboard, _("Toolbars"));
 		break;
 	case GOK_SPY_SEARCH_APPLICATIONS:
 		pKeyboard->Type = KEYBOARD_TYPE_APPLICATIONS;
@@ -2265,19 +2260,9 @@
 		break;
 	case GOK_SPY_SEARCH_MENU:
 	default:
-		switch (role) {
-		case SPI_ROLE_MENU:
-			pKeyboard->Type = KEYBOARD_TYPE_MENUS;
-			gok_keyboard_set_name (pKeyboard, _("Menus"));
-			pKeyboard->search_type = GOK_SPY_SEARCH_MENU;
-			break;
-		case SPI_ROLE_MENU_ITEM:
-		default:
-			pKeyboard->Type = KEYBOARD_TYPE_MENUITEMS;
-			gok_keyboard_set_name (pKeyboard, _("Menu"));   
-			pKeyboard->search_type = GOK_SPY_SEARCH_MENU;
-			break;
-		}
+		pKeyboard->Type = KEYBOARD_TYPE_MENUS;
+		gok_keyboard_set_name (pKeyboard, _("Menu"));
+		pKeyboard->search_type = type;
 		break;
 	}
 	
@@ -2306,7 +2291,7 @@
 * returns: TRUE if the keyboard was displayed, FALSE if not.
 **/
 gboolean 
-gok_keyboard_branch_gui_actions (AccessibleNode* pNodeAccessible)
+gok_keyboard_branch_gui_actions (AccessibleNode* node)
 {
 	AccessibleAction* paaction;
 	gint i = 0;
@@ -2314,40 +2299,11 @@
 		
 	gok_log_enter();
 
-	g_assert(pNodeAccessible != NULL);
-	g_assert(pNodeAccessible->paccessible != NULL);
+	g_assert(node != NULL);
 	
-	/* 
-	 * just in case: before we do any actions check to see if this object has 
-	 * interesting children and if so, branch to them instead.
-	 * Note that this may not be the right thing to do in all cases,
-	 * since it implies that we can't activate the parent's actions.
-	 */
-	gok_log("checking for children with interesting roles");
-	for (i=0; i< NUM_INTERESTING_ROLES; i++)
-	{
-		if (gok_spy_has_child (pNodeAccessible->paccessible, 
-				       GOK_SPY_SEARCH_ROLE, m_InterestingRole[i]) == TRUE)
-		{
-			gok_log_x("Abort action. Branching to child(ren)!");
-			gok_log_leave();
-			if (gok_spy_is_menu_role (m_InterestingRole[i]))
-			{
-				gok_log("a submenu exists...");
-				return gok_keyboard_branch_gui(pNodeAccessible, 
-										   GOK_SPY_SEARCH_MENU,
-										   SPI_ROLE_MENU); 
-			}
-			return gok_keyboard_branch_gui(pNodeAccessible, 
-						       GOK_SPY_SEARCH_ROLE,
-						       m_InterestingRole[i]);
-		}
-	}
-	gok_log("no children with interesting roles");
-
 	/* possible TODO: build a keyboard if more than one action available 
 	(and do this before above branch to children!)*/
-	paaction = Accessible_getAction(pNodeAccessible->paccessible);
+	paaction = Accessible_getAction(node->paccessible);
 	if (paaction != NULL)
 	{
 		/* for now just perform the first action */
@@ -2358,7 +2314,7 @@
 	}	
 
 	/* branch back when a menu item is activated*/
-	if (gok_spy_is_menu_role(Accessible_getRole(pNodeAccessible->paccessible))){
+	if (gok_spy_is_menu_role(Accessible_getRole(node->paccessible))){
 		gok_log_leave();
 		return gok_main_display_scan_previous();
 	}
@@ -2701,7 +2657,7 @@
 {
 	AccessibleHypertext *hypertext = NULL; 
 	AccessibleText *text = NULL;
-	AccessibleNode *node = key->pNodeAccessible;
+	AccessibleNode *node = key->accessible_node;
 	AccessibleHyperlink *link = NULL;
 	gboolean is_editable = FALSE;
 	gboolean activated = FALSE;
@@ -2737,7 +2693,7 @@
 		if (!activated) { /* fallback hack if text is focussable */
 			text = Accessible_getText (node->paccessible);
 			is_editable = Accessible_isEditableText (node->paccessible);
-			if (link && text && node->is_link && !is_editable) {
+			if (link && text && node->flags.is_link && !is_editable) {
 				gboolean is_focussed = FALSE;
 				long int start, end;
 				AccessibleHyperlink_getIndexRange (link, &start, &end);
@@ -3096,10 +3052,10 @@
 			break;
 
 		case KEYTYPE_BRANCHTEXT:
-			if (pKey->pNodeAccessible && 
-				pKey->pNodeAccessible->paccessible) {
+			if (pKey->accessible_node && 
+				pKey->accessible_node->paccessible) {
 					if (gok_keyboard_focus_object 
-						(pKey->pNodeAccessible->paccessible))
+						(pKey->accessible_node->paccessible))
 					{
 						gok_main_display_scan ( NULL, "Keyboard", 
 									KEYBOARD_TYPE_UNSPECIFIED, 
@@ -3257,20 +3213,13 @@
 {
 	GokKeyboard* pKeyboard;
 	GokKey* pKey;
-	gboolean bHasMenuBranch;
-	gboolean bHasToolbarBranch;
-	gboolean bHasGUIBranch;
-	gboolean bHasEditTextBranch;
+	GokSpyUIFlags ui_flags, keyboard_ui_flags;
 	gboolean bChanged;
 
 	gok_log_enter();
 
+	keyboard_ui_flags.value = 0;
 	pKeyboard = gok_main_get_current_keyboard();
-	bHasMenuBranch = FALSE;
-	bHasToolbarBranch = FALSE;
-	bHasGUIBranch = FALSE;
-	bHasEditTextBranch = FALSE;
-	bChanged = FALSE;
 	
 	/* are there any keys that branch to a dynamic keyboard? */
 	pKey = pKeyboard->pKeyFirst;
@@ -3278,35 +3227,33 @@
 	{
 		if (pKey->Type == KEYTYPE_BRANCHMENUS)
 		{
-			bHasMenuBranch = TRUE;
+			keyboard_ui_flags.menus = TRUE;
 		}
 		else if (pKey->Type == KEYTYPE_BRANCHTOOLBARS)
 		{
-			bHasToolbarBranch = TRUE;
+			keyboard_ui_flags.toolbars = TRUE;
 		}
 		else if (pKey->Type == KEYTYPE_BRANCHGUI)
 		{
-			bHasGUIBranch = TRUE;
+			keyboard_ui_flags.gui = TRUE;
 		}
 		else if (pKey->Type == KEYTYPE_BRANCHCOMPOSE)
 		{
-			bHasEditTextBranch = TRUE;
+			keyboard_ui_flags.editable_text = TRUE;
 		}
 		pKey = pKey->pKeyNext;
 	}
 	
 	/* don't do anything if there are no menu and no toolbar keys */
-	if ((bHasMenuBranch == FALSE) &&
-		(bHasToolbarBranch == FALSE) &&
-		(bHasGUIBranch == FALSE) &&
-		(bHasEditTextBranch == FALSE))
+	if (keyboard_ui_flags.value == 0)
 	{
 		gok_log("this keyboard has no dynamic branch keys");
 		gok_log_leave();
 		return bChanged;
 	}
 	
-	/* FIXME - optimize here & in gok-spy -currently too many GUI tree searches.
+	/* build a list of 'relevant' UI components */
+	ui_flags = gok_spy_update_component_list (pAccessibleForeground, keyboard_ui_flags);
 
 	/* enable/disable the branch keys */
 	pKey = pKeyboard->pKeyFirst;
@@ -3314,8 +3261,7 @@
 	{
 		if (pKey->Type == KEYTYPE_BRANCHMENUS)
 		{
-			if (gok_spy_has_child (pAccessibleForeground, 
-					       GOK_SPY_SEARCH_MENU, SPI_ROLE_MENU) == TRUE)
+			if (ui_flags.menus)
 			{
 				/* set this flag if the button state changes */
 				if (strcmp (gtk_widget_get_name(pKey->pButton), "StyleButtonBranchMenus") != 0)
@@ -3342,8 +3288,7 @@
 		}
 		else if (pKey->Type == KEYTYPE_BRANCHTOOLBARS)
 		{
-			if (gok_spy_has_child (pAccessibleForeground, GOK_SPY_SEARCH_ROLE,
-					       SPI_ROLE_TOOL_BAR) == TRUE)
+			if (ui_flags.toolbars)
 			{
 				/* set this flag if the button state changes */
 				if (strcmp (gtk_widget_get_name(pKey->pButton), "StyleButtonBranchToolbars") != 0)
@@ -3370,11 +3315,7 @@
 		}
 		else if (pKey->Type == KEYTYPE_BRANCHGUI)
 		{
-			/* TODO: REFACTOR: enum KeyType */
-			if ((gok_spy_has_child (pAccessibleForeground, 
-						GOK_SPY_SEARCH_ROLE, SPI_ROLE_PUSH_BUTTON) == TRUE) ||
-				(gok_spy_has_child (pAccessibleForeground, 
-						    GOK_SPY_SEARCH_EDITABLE_TEXT, SPI_ROLE_TEXT) == TRUE))
+			if (ui_flags.gui)
 			{
 				/* set this flag if the button state changes */
 				if (strcmp (gtk_widget_get_name(pKey->pButton), "StyleButtonBranchGUI") != 0)
@@ -3401,7 +3342,7 @@
 		}
 		else if (pKey->Type == KEYTYPE_BRANCHCOMPOSE)
 		{
-			if (gok_spy_get_accessibleWithText() != NULL)
+			if (ui_flags.editable_text)
 			{
 				/* set this flag if the button state changes */
 				if (strcmp (gtk_widget_get_name(pKey->pButton), "StyleButtonBranchGUI") != 0)
Index: gok/gok-keyboard.h
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-keyboard.h,v
retrieving revision 1.42
diff -u -r1.42 gok-keyboard.h
--- gok/gok-keyboard.h	17 Nov 2003 13:54:39 -0000	1.42
+++ gok/gok-keyboard.h	28 Nov 2003 14:41:31 -0000
@@ -123,8 +123,6 @@
 	gboolean bCommandPredictionKeysAdded;
 	GokKeyboardExpandPolicy expand;
 	Accessible* pAccessible;
-	AccessibleNode* pNodeAccessible;
-	AccessibleRole  search_role;
 	GokSpySearchType search_type;
 	gboolean bFontCalculated;
 	struct GokKey* pKeyFirst;
@@ -170,7 +168,7 @@
 void gok_keyboard_notify_xkb_event (XkbEvent* event);
 gboolean gok_keyboard_layout (GokKeyboard* pKeyboard, KeyboardLayouts layout, KeyboardShape shape, gboolean force);
 gboolean gok_keyboard_branch_byKey (GokKey* pKey);
-gboolean gok_keyboard_branch_gui (AccessibleNode* pNodeAccessible, GokSpySearchType type, AccessibleRole role);
+gboolean gok_keyboard_branch_gui (AccessibleNode* pNodeAccessible, GokSpySearchType type);
 gboolean gok_keyboard_branch_gui_actions (AccessibleNode* pNodeAccessible);
 gboolean gok_keyboard_branch_edittext (void);
 gboolean gok_chunker_chunk (GokKeyboard* pKeyboard);
Index: gok/gok-spy-priv.h
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-spy-priv.h,v
retrieving revision 1.11
diff -u -r1.11 gok-spy-priv.h
--- gok/gok-spy-priv.h	7 Nov 2003 21:03:38 -0000	1.11
+++ gok/gok-spy-priv.h	28 Nov 2003 14:41:31 -0000
@@ -39,20 +39,32 @@
 GOKSPY_STATE_EVENT
 };
 
+typedef struct
+{
+	union {
+		guint value;
+		struct {
+			guint is_link:1;
+			guint is_ui:1;
+			guint is_menu:1;
+			guint is_toolbar_item:1;
+		};
+	};
+} AccessibleNodeFlags;
+
 /* this structure used in the creation of a linked list of Accessible*, char* (name) pairs */
 typedef struct AccessibleNode
 {
-    struct AccessibleNode* pnext;
     Accessible* paccessible;
-    guint is_link:1;
-    guint link:7; /* FIXME: need to generalize with type-safety, maybe a union? */
+    AccessibleNodeFlags flags;
+    guint link;
     char* pname;
 } AccessibleNode;
 
 /* this structure intended for use with a GQueue */
 typedef struct EventNode
 {
-	Accessible* paccessible;
+	const AccessibleEvent *event;
 	gint type; /* easier than dealing with string data */
 } EventNode;
 
Index: gok/gok-spy.c
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-spy.c,v
retrieving revision 1.98
diff -u -r1.98 gok-spy.c
--- gok/gok-spy.c	15 Nov 2003 17:25:45 -0000	1.98
+++ gok/gok-spy.c	28 Nov 2003 14:41:31 -0000
@@ -76,12 +76,6 @@
 SPIBoolean gok_spy_key_listener (const AccessibleKeystroke *key,
                                  void *user_data);
 
-AccessibleNode* gok_spy_create_list (Accessible *anAccessible,
-				     GokSpySearchType type,
-                                     AccessibleRole anAccessiblerole);
-
-static void gok_spy_find_children (AccessibleNode* pNode, GokSpySearchType type, AccessibleRole Role);
-
 static gboolean gok_spy_has_child_aux (Accessible* accessible,
 				       GokSpySearchType search_type,
                                        AccessibleRole role,
@@ -89,13 +83,14 @@
                                        gint depth, gint cdepth,
                                        gboolean* found);
 
-static AccessibleNode*  gok_spy_append_node (AccessibleNode* pnode,
-                                             Accessible* pAccessible);
+static GSList*  gok_spy_append_node (GSList *nodes,
+				     Accessible* pAccessible,
+				     AccessibleNodeFlags flags);
 
 static void gok_spy_modifier_listener(const AccessibleEvent *event,
                                       void *user_data);
 
-static gboolean gok_spy_worth_searching (Accessible* accessible, AccessibleRole role);
+static gboolean gok_spy_worth_searching (Accessible* accessible);
 
 static void gok_spy_window_activate_listener (const AccessibleEvent *event,
                                               void *user_data);
@@ -107,7 +102,8 @@
                                                 void *user_data);
 
 static gboolean gok_spy_is_visible (Accessible *accessible);
-												
+		
+static void gok_spy_free_nodes (GSList *nodelist);										
 
 /*
  * gok-spy variables
@@ -119,6 +115,8 @@
 static void* m_ptheMouseButtonListener;
 static void* m_ptheStateChangeListener;
 
+static GSList* _priv_ui_nodes = NULL;
+
 /* pointer to the current window */
 static Accessible* m_ptheWindowAccessible;
 
@@ -434,13 +432,14 @@
 		while (g_queue_is_empty(eventQueue) == FALSE)
 		{
 			en = (EventNode*)g_queue_pop_head(eventQueue);
-			gok_spy_accessible_unref(en->paccessible);
+			AccessibleEvent_unref (en->event);
 			g_free(en);
 		}
 		g_queue_free(eventQueue);
 		eventQueue = NULL;
 	}
-	
+	gok_spy_free_nodes (_priv_ui_nodes);
+
 	gok_log_leave ();
 }
 
@@ -533,24 +532,90 @@
 	m_ptheMouseButtonListener = NULL;
 }
 
+/**
+ * gok_spy_node_match:
+ *
+ * 
+ * Returns: TRUE if the node matches search type @type, FALSE otherwise.
+ **/
+gboolean
+gok_spy_node_match (AccessibleNode *node, GokSpySearchType type)
+{
+	fprintf (stderr, "flags=%x, type=%d\n", node->flags.value, type);
+	switch (type)
+	{
+	case GOK_SPY_SEARCH_MENU:
+		return node->flags.is_menu;
+		break;
+	case GOK_SPY_SEARCH_TOOLBARS:
+		return node->flags.is_toolbar_item;
+		break;
+	case GOK_SPY_SEARCH_UI:
+		return node->flags.is_ui;
+		break;
+	case GOK_SPY_SEARCH_EDITABLE_TEXT:
+		if (Accessible_isEditableText (node->paccessible))
+			return TRUE;
+		break;
+	case GOK_SPY_SEARCH_CHILDREN:
+	case GOK_SPY_SEARCH_ALL:
+		return TRUE;
+		break;
+	case GOK_SPY_SEARCH_APPLICATIONS:
+		if (Accessible_isApplication (node->paccessible))
+			return TRUE;
+		break;
+	default:
+		break;
+	}
+	return FALSE;
+}
+
+/**
+ * 
+ * gok_spy_get_children:
+ *
+ **/
+GSList *
+gok_spy_get_children (Accessible *search_root)
+{
+	GSList *nodes = NULL;
+	AccessibleNodeFlags flags;
+	Accessible *child;
+	long child_count;
+	long i;
+
+	g_assert (search_root);
+	/* TODO: should this recurse down, and should we check for 'interesting'-ness first ? */
+	flags.value = 0xff;
+	child_count = Accessible_getChildCount (search_root);
+	for (i = 0; i < child_count; ++i)
+	{
+		child = Accessible_getChildAtIndex (search_root, i);
+		if (child) 
+		{
+			gok_spy_accessible_implicit_ref (child);
+			nodes = gok_spy_append_node (nodes, child, flags);
+			gok_spy_accessible_unref (child);
+		}
+	}
+	return nodes;
+}
+
 /** 
 * gok_spy_get_list 
 * 
 * @paccessible: The parent accessible to the list
-* @type: The type of list to return, i.e. the search criteria
-* @role: The role of the list members
 *
 * User must call gok_spy_free when finished with this list.
 * 
 * Returns: pointer to the list or NULL
 **/ 
-AccessibleNode* gok_spy_get_list( Accessible* paccessible, GokSpySearchType type, AccessibleRole role )
+GSList* gok_spy_get_list( Accessible* paccessible)
 {
-	AccessibleNode* plist = NULL;
-	gok_log_enter();
-	plist = gok_spy_create_list( paccessible, type, role );
-	gok_log_leave();
-	return plist;
+	fprintf (stderr, "getting list of %d nodes\n.", g_slist_length (_priv_ui_nodes));
+	/* TODO: should return a copy, with client-side incremented refs */
+	return _priv_ui_nodes;
 }
 
 /** 
@@ -571,7 +636,7 @@
 }
 
 /**
-* gok_spy_free
+* gok_spy_free_nodes
 *
 * Frees the memory used by the given list. This must be called for every list
 * that is created.
@@ -580,22 +645,22 @@
 *
 * Returns: void
 **/
-void gok_spy_free (AccessibleNode* pNode)
+void gok_spy_free_nodes (GSList *nodes)
 {
-	AccessibleNode* pNodeToFree;
-	pNodeToFree = NULL;
-	
-	gok_log_enter();
-	while (pNode != NULL)
+	GSList *nodelist = nodes;
+	while (nodelist) 
 	{
-		pNodeToFree = pNode;
-		pNode = pNode->pnext;
+		AccessibleNode *node = nodelist->data;
 		/* we gfree this since we've dup'd the SPI string */
-		g_free (pNodeToFree->pname);
-		gok_spy_accessible_unref (pNodeToFree->paccessible);
-		g_free (pNodeToFree);
+		if (node != NULL)
+		{
+			g_free (node->pname);
+			gok_spy_accessible_unref (node->paccessible);
+			g_free (node);
+		}
+		nodelist = nodelist->next;
 	}
-	gok_log_leave();
+	g_slist_free (nodes);
 }
 
 /** 
@@ -685,19 +750,16 @@
 			/* TODO: remove obsolete focus events from queue since process
 			   accessible is expensive. */
 			gok_log("GOKSPY_FOCUS_EVENT");
-			gok_spy_process_accessible(en->paccessible);
+			gok_spy_process_accessible(en->event->source);
 			break;
 		case GOKSPY_STATE_EVENT:
 			gok_log("GOKSPY_STATE_EVENT");
-			/* gok_spy_accessible_ref (en->paccessible); */
-			((AccessibleChangeListenerCB)(m_ptheStateChangeListener))(en->paccessible);
+			((AccessibleChangeListenerCB)(m_ptheStateChangeListener))(en->event->source);
 			break;
 		case GOKSPY_WINDOW_ACTIVATE_EVENT:
 			gok_log("GOKSPY_WINDOW_ACTIVATE_EVENT");
-			/* FIXME !! the ref needs to happen in the original event loop */
-			if (en->paccessible != m_ptheWindowAccessible) {
-				gok_spy_accessible_unref (m_ptheWindowAccessible);
-				m_ptheWindowAccessible = en->paccessible;
+			if (en->event->source != m_ptheWindowAccessible) {
+				m_ptheWindowAccessible = en->event->source;
 				gok_spy_accessible_ref (m_ptheWindowAccessible);
 				((AccessibleChangeListenerCB)(m_ptheWindowChangeListener))(m_ptheWindowAccessible);
 			}
@@ -723,7 +785,7 @@
 			 * events unless they come from what gok thinks
 			 * is the current window.
 			 */
-			if (en->paccessible == m_ptheWindowAccessible) {
+			if (en->event->source == m_ptheWindowAccessible) {
 				gok_spy_accessible_unref (m_ptheWindowAccessible);
 				gok_spy_accessible_unref (m_ptheAccessibleWithText);
 				m_ptheWindowAccessible = NULL;
@@ -735,7 +797,10 @@
 			gok_log_x("unknown event type in internal gok event queue!");
 			break;
 		}
-		gok_spy_accessible_unref (en->paccessible);
+		if (en->event) 
+		{
+			AccessibleEvent_unref (en->event);
+		}
 		g_free(en);
 	}
 	gok_log_leave();
@@ -775,53 +840,34 @@
  * gok_spy_worth_searching:
  *
  * @accessible: the accessible (possibly a parent) to examine for worthiness.
- * @role: the role we are searching for.
  *
  * This function decides if the accessible might have a subtree worth searching.
  *
  * Returns: boolean success. 
 */ 
-gboolean gok_spy_worth_searching (Accessible* accessible, AccessibleRole role)
+gboolean gok_spy_worth_searching (Accessible* accessible)
 {
-	gboolean worthiness;
-	gboolean bmenu;
+	gboolean worthiness = TRUE;
+	gboolean bmenu = FALSE;
 	AccessibleStateSet* ass = NULL;
 
 	gok_log_enter();
-	bmenu = gok_spy_is_menu_role (role);
-	if (bmenu)
-	{		
-		switch (Accessible_getRole(accessible))
-		{
-			/* using this breaks mozilla menus:
-			case SPI_ROLE_TOOL_BAR: */
-			case SPI_ROLE_STATUS_BAR:
-			case SPI_ROLE_COMBO_BOX:
-				/* add cases here */
-				gok_log("aborting menu search");
-				gok_log_leave();
-				return FALSE;
-		}
-	}
-	else
+	
+	switch (Accessible_getRole (accessible)) 
 	{
-		switch (Accessible_getRole(accessible))
-		{
-			case SPI_ROLE_MENU_BAR:
-			case SPI_ROLE_MENU:
-			case SPI_ROLE_COMBO_BOX:
-				/* add cases here */
-				gok_log("aborting search");
-				gok_log_leave();
-				return FALSE;
-		}
+	case SPI_ROLE_MENU:
+	case SPI_ROLE_MENU_BAR:
+	case SPI_ROLE_MENU_ITEM:
+	case SPI_ROLE_CHECK_MENU_ITEM:
+	case SPI_ROLE_RADIO_MENU_ITEM:
+		bmenu = TRUE;
+		break;
+	default:
+		bmenu = FALSE;
 	}
-	
-	worthiness = TRUE;
 	ass = Accessible_getStateSet(accessible);
 	if (ass != NULL)
 	{
-		AccessibleRole role = Accessible_getRole (accessible);
 		/* state heuristic: 
 		 * - if this thing manages its own children, then it 
 		 * is probably not worth traversing.
@@ -869,7 +915,7 @@
     if (accessible == NULL) return *found; 
 	if (cdepth++ == depth) return *found;
 	
-	if (gok_spy_worth_searching(accessible, role) == FALSE) return *found;
+	if (gok_spy_worth_searching(accessible) == FALSE) return *found;
 	
     child_count = Accessible_getChildCount (accessible);
     
@@ -963,7 +1009,8 @@
 static gboolean
 gok_spy_is_ui (Accessible *accessible, AccessibleRole role)
 {
-	gboolean is_interesting_ui_component = FALSE;
+	gboolean interesting = FALSE;
+
 	switch (role) {
 	case SPI_ROLE_PUSH_BUTTON:
 	case SPI_ROLE_CHECK_BOX:
@@ -971,177 +1018,55 @@
 	case SPI_ROLE_RADIO_BUTTON:
 	case SPI_ROLE_PAGE_TAB:
 	case SPI_ROLE_TOGGLE_BUTTON:
-		if (gok_spy_is_visible (accessible))
-			is_interesting_ui_component = TRUE;
-	default:
+		interesting = TRUE;
 		break;
-	}
-	/* EditableText and Hypertext components are always interesting */
-	if (!is_interesting_ui_component) {
+	default:
 		if ((Accessible_isEditableText (accessible)) ||
 		    (Accessible_isHypertext (accessible)))
-			if (gok_spy_is_visible (accessible)) 
-				is_interesting_ui_component = TRUE;
-	}
-	return is_interesting_ui_component;
-}
-
-/**
- * gok_spy_find_children:
- * @pNode: Before execution of this function it is the node that you
- * would like to search for children under.  After execution of this
- * function pNode->pnext is the start of the list of children that
- * satisfy the role requested.  Please note that this function may
- * also modify pNode->paccessible.
- * @role: The role you are searching for.
- *
- * Finds the children of the given node that have the given role.
- * These children are added to the list of children on the node,
- * beginning at pNode->pnext.  Please note that this function may also
- * modify pNode->paccessible.  This is a recursive function.
- */
-void gok_spy_find_children (AccessibleNode* pNode, GokSpySearchType type, AccessibleRole role) 
-{ 
-	Accessible* pAccessibleChild;
-	AccessibleRole childrole;
-	Accessible* pAccessibleParent;
-	long child_count;
-	long i;
-
-	g_assert(pNode != NULL);
-	g_assert(pNode->paccessible != NULL); 
-
-	pAccessibleParent = pNode->paccessible; 
-
-	if (gok_spy_worth_searching(pAccessibleParent, role) == FALSE) return;
-
-	child_count = Accessible_getChildCount (pAccessibleParent);
-
-	if (child_count < 0)
-	{
-		gok_log_x("exception occurred trying to get the child count");
-	}
-
-	/* look through all the children of the given node */
-	for (i=0; i<child_count; i++)
-	{
-		pAccessibleChild
-			= Accessible_getChildAtIndex (pAccessibleParent, i);
-		gok_spy_accessible_implicit_ref (pAccessibleChild);
-
-		if (pAccessibleChild != NULL)
-		{
-			childrole = Accessible_getRole (pAccessibleChild);
-
-			/* check role: special-casing some stuff REFACTOR THIS later TODO */
-			if ((type == GOK_SPY_SEARCH_ALL) /* include everything */
-			    ||
-			    /* include all menu-ish when search type: GOK_SPY_SEARCH_MENU*/
-			    ((type == GOK_SPY_SEARCH_MENU) && 
-			     gok_spy_is_menu_role (childrole))
-			    ||
-			    /* the search role matches the child role */
-			    ((type == GOK_SPY_SEARCH_ROLE) && (childrole == role))
-			    ||
-			    /* all ui */
-			    ((type == GOK_SPY_SEARCH_UI) && 
-			     (gok_spy_is_ui (pAccessibleChild, childrole)))
-			    ||
-				/* editable text */
-			    ((type == GOK_SPY_SEARCH_EDITABLE_TEXT) &&
-			     (Accessible_isEditableText(pAccessibleChild))))
-			{
-				gok_spy_append_node (pNode, pAccessibleChild);
-				if (childrole == SPI_ROLE_PAGE_TAB) {
-					pNode->paccessible = pAccessibleChild;
-					gok_spy_find_children (pNode, type, role);
-				}
-			}
-			else /* search through the children of this child */
-			{
-				pNode->paccessible = pAccessibleChild;
-				gok_spy_find_children (pNode, type, role);
-			}
-
-		gok_spy_accessible_unref (pAccessibleChild);
-
-		}
+			interesting = TRUE;
+		break;
 	}
-}
- 
-/**
- * gok_spy_create_list:
- * @anAccessible: Pointer to parent accessible object.
- * @anAccessibleRole: The role you are searching for.
- *
- * Creates a list of accessible pointers of the given role.
- *
- * Returns: First node in the list of children. Will be NULL if no
- * children found.
- */
-AccessibleNode* gok_spy_create_list (Accessible *anAccessible,
-				     GokSpySearchType type,
-                                     AccessibleRole anAccessibleRole)
-{
-	AccessibleNode nodeRoot;
-
-	gok_log_enter();
-
-	g_assert(anAccessible != NULL);
-
-	nodeRoot.paccessible = anAccessible;
-	nodeRoot.pnext = NULL;
-	nodeRoot.pname = NULL;
-
-	gok_spy_find_children (&nodeRoot, type, anAccessibleRole);
-
-	gok_log_leave();
-	return nodeRoot.pnext;
+	/* EditableText and Hypertext components are always interesting */
+	/* however, invisible UI components are not interesting */
+	return (interesting && gok_spy_is_visible (accessible)); 
 }
 
-static gboolean
-gok_spy_add_node (AccessibleNode *prev, Accessible *accessible, gint i, char *name)
+static GSList *
+gok_spy_add_node (GSList *nodes, Accessible *accessible, AccessibleNodeFlags flags, gint link, char *name)
 {
 	AccessibleNode *newnode = NULL;
 
-	if (!prev) return FALSE;
-
 	newnode = (AccessibleNode*)g_malloc(sizeof(AccessibleNode));
 	
 	if (newnode != NULL) {
 		newnode->paccessible = accessible;
 		gok_spy_accessible_ref (accessible);
-		newnode->is_link = (i >= 0) ? TRUE : FALSE;
-		newnode->link = MAX (0, i);
+		newnode->flags = flags;
+		newnode->link = link;
 		newnode->pname = name;
-		newnode->pnext = NULL;
 		gok_log("newnode->pname = %s", newnode->pname);
-		/* append this to end of list */
-		while (prev->pnext)
-			prev = prev->pnext;
-		prev->pnext = newnode;	
-		return TRUE;
+		nodes = g_slist_append (nodes, newnode);
 	}
-	return FALSE;
+	return nodes;
 }
 
 /**
  * gok_spy_append_node:
- * @pNode: An existing list of AccessibleNode to append to, must be
- * non-NULL.
+ * @pNode: An existing list of AccessibleNode to append to (may be NULL).
  * @pAccessible: The Accessible to append to the list.
+ * @flags: Flags indicating the type of accessible in the node.
  *
  * Creates a new AccessibleNode for pAccessible and appends it to the
  * existing list of AccessibleNode at pNode.  Please note that this
  * function calls gok_spy_accessible_ref (pAccessible) when it
- * attaches it to the AccessibleNode created for it.  Please also note
- * that the list must exist already and pNode must be non-NULL.
+ * attaches it to the AccessibleNode created for it.  
  *
  * Returns: the address of the AccessibleNode created for pAccessible
  * or NULL if problems occur.
  */
-AccessibleNode* gok_spy_append_node (AccessibleNode* pNode,
-                                     Accessible* pAccessible)
+GSList* gok_spy_append_node (GSList* nodes,
+			     Accessible* pAccessible,
+			     AccessibleNodeFlags flags)
 {
 	AccessibleNode* pLastNode = NULL;
 	AccessibleNode* pNewNode = NULL;
@@ -1153,8 +1078,6 @@
 	int j = 0;
 	int ntargets = 0;
 
-	g_assert (pNode != NULL);
-
 	gok_log_enter();
 
         s = Accessible_getName (pAccessible);
@@ -1185,7 +1108,8 @@
 			   * on the link!  But at the moment the link objects are not
 			   * actionable, so we have to fake it.
 			   */
-				gok_spy_add_node (pNode, pAccessible, i, g_strdup (linkname));
+				flags.is_link = TRUE;
+				nodes = gok_spy_add_node (nodes, pAccessible, flags, i, g_strdup (linkname));
 				SPI_freeString (linkname);
 			}
 			Accessible_unref (link_object);
@@ -1194,20 +1118,14 @@
 		AccessibleHypertext_unref (hypertext);
 	}
 
-	/* if the name is empty then try LABELLED_BY, else assign "???" */ 
+	/* for other node types, try to create a reasonable label string */
 	else {
 		/* look for a label */
 		if (pName == NULL)
 		{
 			gok_log("no name, so looking at relations...");
 			relations = Accessible_getRelationSet(pAccessible);
-			/*
-			if (relations == NULL)	{
-				gok_log("no relationset for this object");
-				gok_log_leave();
-				return pNewNode;
-			}
-			*/
+
 			if (relations != NULL)
 			while (relations[i]) {
 				type = AccessibleRelation_getRelationType(relations[i]);
@@ -1264,13 +1182,13 @@
 		if (pName != NULL) {
 			gok_log("we have a name: [%s]",pName);
 			/* create a new node */
-			gok_spy_add_node (pNode, pAccessible, -1, pName);
+			nodes = gok_spy_add_node (nodes, pAccessible, flags, 0, pName);
 		}
 		/* if we decide to allow access to nameless menus ...
 		else if ( Accessible_getRole (pAccessible) == SPI_ROLE_MENU ) {
 			pName = g_strdup (Accessible_getRoleName(pAccessible));
 			gok_log ("Can't think of a good name so using role:[%s]",pName);
-			gok_spy_add_node (pNode, pAccessible, -1, pName);
+			nodes = gok_spy_add_node (nodes, pAccessible, -1, pName);
 		}
 		*/
 		else if (Accessible_isText (pAccessible)) {
@@ -1329,19 +1247,15 @@
 			}
 			if (pName != NULL) {
 				gok_log ("we have a name: [%s]",pName);
-				gok_spy_add_node (pNode, pAccessible, -1, pName);
+				nodes = gok_spy_add_node (nodes, pAccessible, flags, 0, pName);
 			}
 		}
 			
 	}
 	
-	
-	while (pNode->pnext) 
-		pNode = pNode->pnext;
-
 	gok_log_leave();
 
-	return pNode;
+	return nodes;
 }
 
 /** 
@@ -1353,9 +1267,9 @@
 { 
 	EventNode* en; 
 	gok_log_enter();
-	gok_spy_accessible_ref(event->source);
+	AccessibleEvent_ref (event);
 	en = (EventNode*)g_malloc(sizeof(EventNode));
-	en->paccessible = event->source;
+	en->event = event;
 	en->type = GOKSPY_FOCUS_EVENT;
 	g_queue_push_tail( eventQueue, en );
 
@@ -1375,7 +1289,7 @@
 
 	if (event->source == m_ptheWindowAccessible) {
 		en = (EventNode*) g_malloc(sizeof(EventNode));
-		en->paccessible = NULL; /* the source accessible is defunct! */
+		en->event = NULL;
 		en->type = GOKSPY_DEFUNCT_EVENT;
 		g_queue_push_tail ( eventQueue, en );
 		gok_spy_add_idle_handler ();
@@ -1392,9 +1306,9 @@
 	EventNode *en;
 	gok_log_enter ();
 
-	gok_spy_accessible_ref (event->source);
-	en = (EventNode*)g_malloc (sizeof (EventNode));
-	en->paccessible = event->source;
+	AccessibleEvent_ref (event);
+	en = (EventNode*) g_malloc (sizeof (EventNode));
+	en->event = event;
 	en->type = GOKSPY_WINDOW_ACTIVATE_EVENT;
 	g_queue_push_tail (eventQueue, en);
 	gok_spy_add_idle_handler ();
@@ -1409,9 +1323,9 @@
 	EventNode *en;
 	gok_log_enter ();
 
-	gok_spy_accessible_ref (event->source);
+	AccessibleEvent_ref (event);
 	en = (EventNode*)g_malloc (sizeof (EventNode));
-	en->paccessible = event->source;
+	en->event = event;
 	en->type = GOKSPY_WINDOW_DEACTIVATE_EVENT;
 	g_queue_push_tail (eventQueue, en);
 	gok_spy_add_idle_handler ();
@@ -1427,9 +1341,9 @@
 	EventNode *en;
 	gok_log_enter ();
 
-	gok_spy_accessible_ref (event->source);
+	AccessibleEvent_ref (event);
 	en = (EventNode*)g_malloc (sizeof (EventNode));
-	en->paccessible = event->source;
+	en->event = event;
 	en->type = GOKSPY_STATE_EVENT;
 	g_queue_push_tail (eventQueue, en);
 	gok_spy_add_idle_handler ();
@@ -1707,6 +1621,131 @@
 	return NULL;
 }
 
+static Accessible*
+gok_spy_get_toolbar_item (Accessible *toolbar_child)
+{
+	/* 
+	 * ROLE_TOOLBAR containers can have ROLE_PANEL or similarly useless children;
+	 * we need to drill down to the useful thingy i.e. pushbutton, etc.
+	 */
+	Accessible *parent = toolbar_child;
+	Accessible_ref (parent);
+	while (parent) 
+	{
+		Accessible *child = Accessible_getChildAtIndex (parent, 0);
+		Accessible_unref (parent);
+		if (child && Accessible_isAction (child)) 
+			return child;
+		else 
+			parent = child;
+	}
+	return NULL;
+}
+
+static GokSpyUIFlags 
+gok_spy_search_component_list (Accessible *rootAccessible, GokSpyUIFlags keyboard_ui_flags)
+{
+	Accessible* child;
+	Accessible* parent;
+	AccessibleRole role;
+	AccessibleRole parent_role;
+	GokSpyUIFlags ui_flags;
+	long child_count;
+	long i;
+
+	ui_flags.value = 0;
+	parent = rootAccessible;
+	
+	if (gok_spy_worth_searching (parent) == FALSE) 
+	{
+		fprintf (stderr, "not worth searching.\n");
+		return ui_flags;
+	}	
+	parent_role = Accessible_getRole (parent);
+	child_count = Accessible_getChildCount (parent);
+	for (i = 0; i < child_count; ++i)
+	{
+		AccessibleNodeFlags flags;
+		flags.value = 0;
+		child = Accessible_getChildAtIndex (parent, i);
+		gok_spy_accessible_implicit_ref (child);
+		if (child)
+		{
+			flags.value = 0;
+			role = Accessible_getRole (child);
+			if (keyboard_ui_flags.menus && gok_spy_is_menu_role (role))
+			{
+				fprintf (stderr, "menu\n");
+				ui_flags.menus = flags.is_menu = TRUE;
+			}
+			else if (keyboard_ui_flags.toolbars && 
+				 parent_role == SPI_ROLE_TOOL_BAR)
+			{
+				Accessible *toolbar_item = gok_spy_get_toolbar_item (child);
+				if (keyboard_ui_flags.gui) 
+					flags.is_ui = TRUE; /* toolbar items are ui elements too */
+				ui_flags.toolbars = flags.is_toolbar_item = TRUE;
+				_priv_ui_nodes = gok_spy_append_node (_priv_ui_nodes, toolbar_item, flags);
+				fprintf (stderr, "toolbar\n");
+			}
+			else if (keyboard_ui_flags.gui && !flags.is_menu && gok_spy_is_ui (child, role))
+			{
+				ui_flags.gui = flags.is_ui = TRUE;
+				if (keyboard_ui_flags.editable_text && Accessible_isEditableText (child)) 
+				{
+					ui_flags.editable_text = TRUE;
+					fprintf (stderr, "editable-text\n");
+				}
+				fprintf (stderr, "ui\n");
+			}
+			if (!flags.is_toolbar_item) /* toolbar items already added */
+			{
+				if (flags.value) 
+				{
+					_priv_ui_nodes = gok_spy_append_node (_priv_ui_nodes, child, flags);
+				}
+				else
+				{
+					ui_flags.value |= gok_spy_search_component_list (child, keyboard_ui_flags).value;
+				}
+			}
+			gok_spy_accessible_unref (child);
+		}
+	}	
+
+	return ui_flags;
+}
+
+
+/**
+ * gok_spy_update_component_list:
+ *
+ * Call this to update GOK's internal list of 'interesting UI components'.
+ * It searches the topmost accessible of the currently-focussed window 
+ * (which should be passed in as @rootAccessible), and update's GOK's list
+ * based on the relevant children.  
+ *
+ * returns: A set of flags indicating the types of UI components available in
+ *          the context specified by @rootAccessible.
+ **/
+GokSpyUIFlags 
+gok_spy_update_component_list (Accessible *rootAccessible, GokSpyUIFlags keyboard_ui_flags)
+{
+	GokSpyUIFlags ui_flags;
+
+	gok_spy_free_nodes (_priv_ui_nodes);
+	_priv_ui_nodes = NULL;
+
+	fprintf (stderr, "updating component list [flags=%x]...", keyboard_ui_flags.value);
+
+	ui_flags = gok_spy_search_component_list (rootAccessible, keyboard_ui_flags);
+
+	fprintf (stderr, "found %d components [flags=%x].\n", 
+		 g_slist_length (_priv_ui_nodes), ui_flags.value);
+
+	return ui_flags;
+}
+
 /*
 gboolean gok_spy_is_desktop(Accessible* pAccessible)
 {
@@ -1780,3 +1819,4 @@
 	gok_log_leave();
 }
 */
+
Index: gok/gok-spy.h
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-spy.h,v
retrieving revision 1.28
diff -u -r1.28 gok-spy.h
--- gok/gok-spy.h	7 Nov 2003 13:47:32 -0000	1.28
+++ gok/gok-spy.h	28 Nov 2003 14:41:31 -0000
@@ -38,13 +38,32 @@
 
 typedef enum {
 	GOK_SPY_SEARCH_ROLE,
+	GOK_SPY_SEARCH_TOOLBARS,
 	GOK_SPY_SEARCH_MENU,
 	GOK_SPY_SEARCH_UI,
 	GOK_SPY_SEARCH_EDITABLE_TEXT,
 	GOK_SPY_SEARCH_APPLICATIONS,
+	GOK_SPY_SEARCH_CHILDREN,
 	GOK_SPY_SEARCH_ALL
 } GokSpySearchType;
 
+typedef struct {
+	AccessibleNodeFlags match_flags;
+} GokSpyMatchCondition;
+
+typedef struct
+{
+	union {
+		guint value;
+		struct {
+			guint menus:1;
+			guint toolbars:1;
+			guint gui:1;
+			guint editable_text:1;
+		};
+	};
+} GokSpyUIFlags;
+
 void gok_spy_open(void);        /* call this first (user must call SPI_init first) */
 void gok_spy_close(void);       /* call this when shutting down */ 
 void gok_spy_stop (void);       /* call this first, as soon as you start shutting down */
@@ -67,16 +86,18 @@
 gboolean gok_spy_is_menu_role (AccessibleRole role);
 /* gboolean gok_spy_is_desktop(Accessible* pAccessible); */
 /* gboolean gok_spy_accessible_is_desktopChild(Accessible* accessible); */
-Accessible* gok_spy_get_active_frame( void );
-AccessibleNode* gok_spy_get_list( Accessible* paccessible, GokSpySearchType type, AccessibleRole role ); 
-AccessibleNode* gok_spy_get_ui_list( Accessible* paccessible); 
-AccessibleNode* gok_spy_refresh( AccessibleNode* plist); 
-void gok_spy_free( AccessibleNode* plist ); /* call this to free up an uneeded list's memory */ 
+Accessible*     gok_spy_get_active_frame (void );
+GSList*         gok_spy_get_list (Accessible* paccessible); 
+GSList*         gok_spy_get_children (Accessible* paccessible); 
+GokSpyUIFlags   gok_spy_update_component_list (Accessible* accessible, GokSpyUIFlags keyboard_ui_flags);
+AccessibleNode* gok_spy_get_ui_list (Accessible* paccessible); 
+AccessibleNode* gok_spy_refresh (AccessibleNode* plist); 
+void            gok_spy_free (GSList *nodes); /* call this to free up an uneeded list's memory */ 
 
-Accessible* gok_spy_get_accessibleWithText(void);
+Accessible*     gok_spy_get_accessibleWithText(void);
 
 gboolean gok_spy_has_child (Accessible* accessible, GokSpySearchType type, AccessibleRole role); 
-
+gboolean gok_spy_node_match (AccessibleNode *node, GokSpySearchType type);
 gboolean gok_spy_check_queues(void);
 gboolean gok_spy_check_window(AccessibleRole role);
 void gok_spy_add_idle_handler (void);
Index: gok/gok-word-complete.c
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-word-complete.c,v
retrieving revision 1.26
diff -u -r1.26 gok-word-complete.c
--- gok/gok-word-complete.c	4 Nov 2003 13:40:12 -0000	1.26
+++ gok/gok-word-complete.c	28 Nov 2003 14:41:31 -0000
@@ -52,15 +52,15 @@
 	                                         GokWordComplete *complete, gunichar letter);
 static gchar **gok_wordcomplete_real_predict (GokWordComplete *complete, gint num_predictions);
 static gchar *gok_wordcomplete_real_get_word_part (GokWordComplete *complete);
-static gchar *  gok_wordcomplete_real_get_aux_dict (GokWordComplete *complete);
-static gboolean gok_wordcomplete_real_set_aux_dict (GokWordComplete *complete, const gchar *dict_path);
+static const gchar *  gok_wordcomplete_real_get_aux_dict (GokWordComplete *complete);
+static gboolean gok_wordcomplete_real_set_aux_dict (GokWordComplete *complete, gchar *dict_path);
 
 struct _GokWordCompletePrivate 
 {
         /* the word, or part word, that is getting completed */
 	gchar     *word_part;
 	gunichar     compose;
-	const gchar *aux_dictionaries;
+	gchar *aux_dictionaries;
 };
 
 static GokWordComplete *default_wordcomplete_engine = NULL;
@@ -316,7 +316,7 @@
 * 
 * returns: a fully-delimited file path to an auxiliary word prediction dictionary
 **/
-gchar*   
+const gchar*   
 gok_wordcomplete_get_aux_dictionaries (GokWordComplete *complete)
 {
 	GokWordCompleteClass *klass = GOK_WORDCOMPLETE_GET_CLASS (complete);
@@ -332,7 +332,7 @@
 * returns: TRUE if an aux dictionary can be used by the word-completion engine, FALSE otherwise.
 **/
 gboolean 
-gok_wordcomplete_set_aux_dictionaries (GokWordComplete *complete, const gchar *dictionary_path)
+gok_wordcomplete_set_aux_dictionaries (GokWordComplete *complete, gchar *dictionary_path)
 {
 	GokWordCompleteClass *klass = GOK_WORDCOMPLETE_GET_CLASS (complete);
 	if (*klass->set_aux_dictionary)
@@ -636,7 +636,7 @@
 
 /**
  **/
-static gchar *
+static const gchar *
 gok_wordcomplete_real_get_aux_dict (GokWordComplete *complete)
 {
 	return complete->priv->aux_dictionaries;
@@ -645,7 +645,7 @@
 /**
  **/
 static gboolean
-gok_wordcomplete_real_set_aux_dict (GokWordComplete *complete, const gchar *dict_path)
+gok_wordcomplete_real_set_aux_dict (GokWordComplete *complete, gchar *dict_path)
 {
 	if (complete && complete->priv)
 		complete->priv->aux_dictionaries = dict_path;
Index: gok/gok-word-complete.h
===================================================================
RCS file: /cvs/gnome/gok/gok/gok-word-complete.h,v
retrieving revision 1.13
diff -u -r1.13 gok-word-complete.h
--- gok/gok-word-complete.h	14 Nov 2003 17:39:15 -0000	1.13
+++ gok/gok-word-complete.h	28 Nov 2003 14:41:31 -0000
@@ -77,7 +77,7 @@
 	GokWordCompletionCharacterCategory (* unichar_get_category) (GokWordComplete *complete, gunichar letter);
 	gchar*    (* get_word_part) (GokWordComplete *complete);
         const gchar*    (* get_aux_dictionary) (GokWordComplete *complete);
-	gboolean  (* set_aux_dictionary) (GokWordComplete *complete, const gchar *dict_path);
+	gboolean  (* set_aux_dictionary) (GokWordComplete *complete, gchar *dict_path);
 };
 
 gboolean gok_wordcomplete_open           (GokWordComplete *complete, gchar *directory);
@@ -95,8 +95,8 @@
 					       gint num_predictions);
 
 gchar*   gok_wordcomplete_get_word_part (GokWordComplete *complete);
-gchar*   gok_wordcomplete_get_aux_dictionaries (GokWordComplete *complete);
-gboolean gok_wordcomplete_set_aux_dictionaries (GokWordComplete *complete, const gchar *dictionary_path);
+const gchar*   gok_wordcomplete_get_aux_dictionaries (GokWordComplete *complete);
+gboolean gok_wordcomplete_set_aux_dictionaries (GokWordComplete *complete, gchar *dictionary_path);
 
 #ifdef __cplusplus
 }
Index: gok/main.c
===================================================================
RCS file: /cvs/gnome/gok/gok/main.c,v
retrieving revision 1.125
diff -u -r1.125 main.c
--- gok/main.c	19 Nov 2003 13:32:10 -0000	1.125
+++ gok/main.c	28 Nov 2003 14:41:31 -0000
@@ -359,7 +359,8 @@
 	/* initialize the word prediction engine with gconf values */
 	if (gok_data_get_use_aux_dictionaries ())
 		gok_wordcomplete_set_aux_dictionaries (gok_wordcomplete_get_default (),
-						       gok_data_get_aux_dictionaries ());
+						       (gchar *) gok_data_get_aux_dictionaries ());
+	/* cast silences compiler; we are discarding 'const' */
 
 	gok_log ("gok_data_initialize has finished");
 
@@ -494,7 +495,7 @@
 gok_log ("finished check");
 	
 	/* connect signal handlers; don't trap SIGKILL */ 
-	signal(SIGSEGV, (void (*)(int))gok_sig_handler); 
+/*	signal(SIGSEGV, (void (*)(int))gok_sig_handler); */
 	signal(SIGTERM, (void (*)(int))gok_sig_handler);
 	signal(SIGINT,  (void (*)(int))gok_sig_handler);
 
@@ -673,27 +674,33 @@
 	if (pKB != NULL) {
 		pK = pKB->pKeyFirst;
 		while (pK != NULL) {
-			if (pK->pNodeAccessible != NULL) {
-				if (pK->pNodeAccessible->paccessible == pAccessible) {
-					/* note: this is very specific for now because we are doing
-					   this to make sure checkbox and radio menu item state
-					   is represented properly. TODO: generalize
-					*/
-					ass = Accessible_getStateSet(pAccessible);
-					if (AccessibleStateSet_contains( ass, SPI_STATE_CHECKED )) {
-						pK->ComponentState.active = TRUE;
-					}
-					else {
-						pK->ComponentState.active = FALSE;
-					}
-					AccessibleStateSet_unref(ass);
-					gok_key_update_toggle_state (pK);
- 					break;
+			if (pK->accessible_node && (pK->accessible_node->paccessible == pAccessible)) {
+				/* note: this is very specific for now because we are doing
+				   this to make sure checkbox and radio menu item state
+				   is represented properly. TODO: generalize
+				*/
+				ass = Accessible_getStateSet(pAccessible);
+				if (AccessibleStateSet_contains( ass, SPI_STATE_CHECKED )) {
+					pK->ComponentState.active = TRUE;
 				}
+				else {
+					pK->ComponentState.active = FALSE;
+				}
+				AccessibleStateSet_unref(ass);
+				gok_key_update_toggle_state (pK);
+				break;
 			}
 			pK = pK->pKeyNext;
 		}
 	}
+
+	/* notes:
+	   we now check to see if the current keyboard requires updating, currently
+	   we simply call gok_main_ds, but if this is too slow we can create a 
+	   method that updates the specific key in question 
+	   wph - I deleted the code that was commented out, don't think it would work
+	   for us - wph
+	*/
 }	
 
 
