]> Pileus Git - ~andy/gtk/blob - gtk/a11y/tests/testlib.c
gail: No need to include modules/other in CFLAGS anymore
[~andy/gtk] / gtk / a11y / tests / testlib.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include "testlib.h" 
5
6 static gint     _get_position_in_array          (gint           window,
7                                                 gchar           *the_test_name);
8 static gint     _get_position_in_parameters     (gint           window,
9                                                 gchar           *label,
10                                                 gint            position);
11 static void     _create_output_window           (OutputWindow   **outwin);
12 static gboolean _create_select_tests_window     (AtkObject      *obj,
13                                                 TLruntest       runtest,
14                                                 OutputWindow    **outwin);
15 static void     _toggle_selectedcb              (GtkWidget      *widget,
16                                                 gpointer        test);
17 static void     _testselectioncb                (GtkWidget      *widget,
18                                                 gpointer        data);
19 static void     _destroy                        (GtkWidget      *widget,
20                                                 gpointer        data);
21
22 /* General functions */
23
24 /**
25  * find_object_by_role:
26  * @obj: An #AtkObject
27  * @roles: An array of roles to search for
28  * @num_roles: The number of entries in @roles
29  *
30  * Find the #AtkObject which is a decendant of the specified @obj
31  * which is of an #AtkRole type specified in the @roles array.
32  *
33  * Returns: the #AtkObject that meets the specified criteria or NULL
34  * if no object is found. 
35  **/
36 AtkObject*
37 find_object_by_role (AtkObject *obj,
38                      AtkRole   *roles,
39                      gint      num_roles)
40 {
41   /*
42    * Find the first object which is a descendant of the specified object
43    * which matches the specified role.
44    *
45    * This function returns a reference to the AtkObject which should be
46    * removed when finished with the object.
47    */
48   gint i, j;
49   gint n_children;
50   AtkObject *child;
51
52   if (obj == NULL)
53     return NULL;
54
55   for (j=0; j < num_roles; j++)
56     {
57       if (atk_object_get_role (obj) == roles[j])
58         return obj;
59     }
60
61   n_children = atk_object_get_n_accessible_children (obj);
62   for (i = 0; i < n_children; i++)
63     {
64       AtkObject* found_obj;
65
66       child = atk_object_ref_accessible_child (obj, i);
67
68       if (child == NULL)
69         continue;
70
71       for (j=0; j < num_roles; j++)
72         {
73           if (atk_object_get_role (child) == roles[j])
74             return child;
75         }
76
77       found_obj = find_object_by_role (child, roles, num_roles);
78       g_object_unref (child);
79       if (found_obj)
80         return found_obj;
81     }
82   return NULL;
83 }
84
85 /**
86  * find_object_by_name_and_role:
87  * @obj: An #AtkObject
88  * @name: The GTK widget name
89  * @roles: An array of roles to search for
90  * @num_roles: The number of entries in @roles
91  *
92  * Find the #AtkObject which is a decendant of the specified @obj
93  * which is of an #AtkRole type specified in the @roles array which
94  * also has the GTK widget name specified in @name.
95  *
96  * Returns: the #AtkObject that meets the specified criteria or NULL
97  * if no object is found. 
98  **/
99 AtkObject*
100 find_object_by_name_and_role(AtkObject   *obj,
101                              const gchar *name,
102                              AtkRole     *roles,
103                              gint        num_roles)
104 {
105   AtkObject *child;
106   GtkWidget* widget;
107   gint i, j;
108   gint n_children;
109
110   if (obj == NULL)
111     return NULL;
112
113   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
114   if (GTK_IS_WIDGET (widget))
115     {
116       if (strcmp (name, gtk_widget_get_name(GTK_WIDGET (widget))) == 0)
117         {
118           for (j=0; j < num_roles; j++)
119             {
120               if (atk_object_get_role (obj) == roles[j])
121                 return obj;
122             }
123         }
124     }
125
126   n_children = atk_object_get_n_accessible_children (obj);
127   for (i = 0; i < n_children; i++)
128     {
129       AtkObject* found_obj;
130  
131       child = atk_object_ref_accessible_child (obj, i);
132
133       if (child == NULL)
134         continue;
135
136       widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (child));
137       if (GTK_IS_WIDGET (widget))
138         {
139           if (strcmp(name, gtk_widget_get_name(GTK_WIDGET (widget))) == 0)
140             {
141               for (j=0; j < num_roles; j++)
142                 {
143                   if (atk_object_get_role (child) == roles[j])
144                     return child;
145                 }
146             }
147         }
148       found_obj = find_object_by_name_and_role (child, name, roles, num_roles);
149       g_object_unref (child);
150       if (found_obj)
151         return found_obj;
152     }
153   return NULL;
154 }
155
156 /**
157  * find_object_by_accessible_name_and_role:
158  * @obj: An #AtkObject
159  * @name: The accessible name
160  * @roles: An array of roles to search for
161  * @num_roles: The number of entries in @roles
162  *
163  * Find the #AtkObject which is a decendant of the specified @obj
164  * which has the specified @name and matches one of the 
165  * specified @roles.
166  * 
167  * Returns: the #AtkObject that meets the specified criteria or NULL
168  * if no object is found. 
169  */
170 AtkObject*
171 find_object_by_accessible_name_and_role (AtkObject   *obj,
172                                          const gchar *name,
173                                          AtkRole     *roles,
174                                          gint        num_roles)
175 {
176   AtkObject *child;
177   gint i, j;
178   gint n_children;
179   const gchar *accessible_name;
180
181   if (obj == NULL)
182     return NULL;
183
184   accessible_name = atk_object_get_name (obj);
185   if (accessible_name && (strcmp(name, accessible_name) == 0))
186     {
187       for (j=0; j < num_roles; j++)
188         {
189           if (atk_object_get_role (obj) == roles[j])
190             return obj;
191         }
192     }
193
194   n_children = atk_object_get_n_accessible_children (obj);
195   for (i = 0; i < n_children; i++)
196     {
197       AtkObject* found_obj;
198
199       child = atk_object_ref_accessible_child (obj, i);
200
201       if (child == NULL)
202         continue;
203
204       accessible_name = atk_object_get_name (child);
205       if (accessible_name && (strcmp(name, accessible_name) == 0))
206         {
207           for (j=0; j < num_roles; j++)
208             {
209               if (atk_object_get_role (child) == roles[j])
210                 return child;
211             }
212         }
213       found_obj = find_object_by_accessible_name_and_role (child, name, 
214                                                            roles, num_roles);
215       g_object_unref (child);
216       if (found_obj)
217         return found_obj;
218     }
219   return NULL;
220 }
221
222 /**
223  * find_object_by_name_and_role:
224  * @obj: An #AtkObject
225  * @type: The type 
226  *
227  * Find the #AtkObject which is a decendant of the specified @obj
228  * which has the specified @type.
229  * 
230  * Returns: the #AtkObject that meets the specified criteria or NULL
231  * if no object is found. 
232  */
233 AtkObject*
234 find_object_by_type (AtkObject *obj, 
235                      gchar     *type)
236 {
237   /*
238    * Find the first object which is a descendant of the specified object
239    * which matches the specified type.
240    *
241    * This function returns a reference to the AtkObject which should be
242    * removed when finished with the object.
243    */
244   gint i;
245   gint n_children;
246   AtkObject *child;
247   const gchar * typename = NULL;
248
249   if (obj == NULL)
250     return NULL;
251
252   typename = g_type_name (G_OBJECT_TYPE (obj));
253   if (strcmp (typename, type) == 0)
254      return obj;
255
256   n_children = atk_object_get_n_accessible_children (obj);
257   for (i = 0; i < n_children; i++)
258     {
259       AtkObject* found_obj;
260
261       child = atk_object_ref_accessible_child (obj, i);
262
263       if (child == NULL)
264         continue;
265
266       typename = g_type_name (G_OBJECT_TYPE (child));
267
268       if (strcmp (typename, type) == 0)
269         return child;
270
271       found_obj = find_object_by_type (child, type);
272       g_object_unref (child);
273       if (found_obj)
274         return found_obj;
275     }
276   return NULL;
277 }
278
279 /**
280  * already_accessed_atk_object
281  * @obj: An #AtkObject
282  *
283  * Keeps a static GPtrArray of objects that have been passed into this
284  * function. 
285  *
286  * Returns: TRUE if @obj has been passed into this function before
287  * and FALSE otherwise.
288  */
289 gboolean
290 already_accessed_atk_object (AtkObject *obj)
291 {
292   static GPtrArray *obj_array = NULL;
293   gboolean found = FALSE;
294   gint i;
295
296   /*
297    * We create a property handler for each object if one was not associated
298    * with it already.
299    *
300    * We add it to our array of objects which have property handlers; if an
301    * object is destroyed it remains in the array.
302    */
303   if (obj_array == NULL)
304     obj_array = g_ptr_array_new ();
305
306   for (i = 0; i < obj_array->len; i++)
307     {
308       if (obj == g_ptr_array_index (obj_array, i))
309         {
310           found = TRUE;
311           break;
312         }
313     }
314   if (!found)
315     g_ptr_array_add (obj_array, obj);
316
317   return found;
318 }
319
320 /**
321  * display_children
322  * @obj: An #AtkObject
323  * @depth: Number of spaces to indent output.
324  * @child_number: The child number of this object.
325  *
326  * Displays the hierarchy of widgets starting from @obj.
327  **/
328 void
329 display_children (AtkObject *obj, 
330                   gint      depth, 
331                   gint      child_number)
332 {
333   display_children_to_depth(obj, -1, depth, child_number);
334 }
335
336 /**
337  * display_children_to_depth
338  * @obj: An #AtkObject
339  * @to_depth: Display to this depth.
340  * @depth: Number of spaces to indent output.
341  * @child_number: The child number of this object.
342  *
343  * Displays the hierarchy of widgets starting from @obj only
344  * to the specified depth.
345  **/
346 void
347 display_children_to_depth (AtkObject *obj,
348                            gint      to_depth,
349                            gint      depth,
350                            gint      child_number)
351 {
352   AtkRole role;
353   const gchar *rolename;
354   const gchar *typename;
355   gint n_children, parent_index, i;
356
357   if (to_depth >= 0 && depth > to_depth)
358      return;
359
360   if (obj == NULL)
361      return;
362
363   for (i=0; i < depth; i++)
364     g_print(" ");
365
366   role = atk_object_get_role (obj);
367   rolename = atk_role_get_name (role);
368
369  /*
370   * Note that child_number and parent_index should be the same
371   * unless there is an error.
372   */
373   parent_index = atk_object_get_index_in_parent(obj);
374   g_print("child <%d == %d> ", child_number, parent_index);
375
376   n_children = atk_object_get_n_accessible_children (obj);
377   g_print ("children <%d> ", n_children);
378
379   if (rolename)
380     g_print("role <%s>, ", rolename);
381   else
382     g_print("role <error>");
383
384   if (GTK_IS_ACCESSIBLE(obj))
385     {
386       GtkWidget *widget;
387
388       widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
389       g_print("name <%s>, ", gtk_widget_get_name(GTK_WIDGET (widget)));
390     }
391   else
392     g_print("name <NULL>, ");
393
394   typename = g_type_name (G_OBJECT_TYPE (obj));
395   g_print ("typename <%s>\n", typename);
396
397   for (i = 0; i < n_children; i++)
398     {
399       AtkObject *child;
400
401       child = atk_object_ref_accessible_child (obj, i);
402       if (child != NULL)
403         {
404           display_children_to_depth (child, to_depth, depth + 1, i);
405           g_object_unref (G_OBJECT (child));
406         }
407     }
408 }
409
410 /* Test GUI logic */
411
412 /* GUI Information for the Select Tests Window */
413 typedef struct
414 {
415   GtkWidget     *selecttestsWindow;
416   GtkWidget     *hbox;
417   GtkWidget     *vbox;
418   GtkWidget     *label;
419   GtkWidget     *textInsert;
420   GtkWidget     *button;
421   gchar         *selecttestsTitle;
422 }MainDialog;
423
424 /* Functionality information about each added test */
425 typedef struct
426 {
427   GtkWidget     *toggleButton;
428   GtkWidget     *hbox;
429   GtkWidget     *parameterLabel[MAX_PARAMS];
430   GtkWidget     *parameterInput[MAX_PARAMS];
431   gchar         *testName;
432   gint          numParameters;
433 }TestList;
434
435 typedef struct
436 {
437    TLruntest   runtest;
438    AtkObject*  obj;
439    gint        win_num;
440 }TestCB;
441
442 static MainDialog      *md[MAX_WINDOWS];
443 static OutputWindow    *ow;
444
445 /* An array containing function information on all of the tests */
446 static TestList        listoftests[MAX_WINDOWS][MAX_TESTS];
447
448 /* A counter for the actual number of added tests */
449 gint                   counter;
450
451 /* A global for keeping track of the window numbers */
452 static gint            window_no = 0;
453 /* An array containing the names of the tests that are "on" */
454 static gchar           *onTests[MAX_WINDOWS][MAX_TESTS]; 
455 static gint            g_visibleDialog = 0;
456 static gint            testcount[MAX_WINDOWS];
457 static TestCB          testcb[MAX_WINDOWS];
458
459 /**
460  * create_windows:
461  * @obj: An #AtkObject
462  * @runtest: The callback function to run when the "Run Tests" button
463  *   is clicked.
464  * @outwin: The output window to use.  If NULL is passed in, then 
465  *   create a new one.
466  *
467  * Creates the test window and the output window (if @outwin is NULL)
468  * Runs _create_output_window() and _create_select_tests_window() 
469  * and sets g_visibleDialog to 1
470  *
471  * Returns: The window number of the created window if successful, -1 otherwise.
472  **/
473 gint
474 create_windows (AtkObject    *obj,
475                 TLruntest    runtest,
476                 OutputWindow **outwin)
477 {
478   gboolean valid;  
479   gint tmp;
480
481   g_visibleDialog = 1;
482   _create_output_window(outwin); 
483   valid = _create_select_tests_window(obj, runtest, outwin);
484   if (valid)
485     {
486       tmp = window_no;
487       window_no++;
488       return tmp;
489     }
490   else
491     return -1;
492 }
493
494 /** 
495  * _create_output_window
496  * @outwin: If outwin is passed in as NULL, a new output window is created
497  *   otherwise, the outwin passed in is shared.
498  *
499  * Creates the Test Result Output Window .
500  **/
501 static void
502 _create_output_window (OutputWindow **outwin)
503 {
504   GtkWidget *view;
505   GtkWidget *scrolled_window;
506   OutputWindow *localow;
507
508   if (*outwin == NULL)
509     {
510       localow = (OutputWindow *) malloc (sizeof(OutputWindow));
511    
512       localow->outputBuffer = gtk_text_buffer_new(NULL);
513       view = gtk_text_view_new_with_buffer(GTK_TEXT_BUFFER(localow->outputBuffer));
514       gtk_widget_set_size_request (view, 700, 500);
515       gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD);
516       gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE);   
517
518       localow->outputWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
519       gtk_window_set_title(GTK_WINDOW(localow->outputWindow), "Test Output");
520       scrolled_window = gtk_scrolled_window_new(NULL, NULL);
521
522       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
523                                      GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
524       gtk_container_add(GTK_CONTAINER(localow->outputWindow), scrolled_window);
525       gtk_container_add(GTK_CONTAINER(scrolled_window), view);
526       gtk_text_buffer_get_iter_at_offset(localow->outputBuffer, &localow->outputIter, 0);
527       gtk_widget_show(view);
528       gtk_widget_show(scrolled_window);
529       gtk_widget_show(localow->outputWindow);
530
531       gtk_text_buffer_set_text(GTK_TEXT_BUFFER(localow->outputBuffer),
532         "\n\nWelcome to the test GUI:\nTest results are printed here\n\n", 58);
533       gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(localow->outputBuffer),
534                                           &localow->outputIter, 0);
535       *outwin = localow;
536       ow = *outwin;
537     }
538 }
539
540 /** 
541  * _create_select_tests_window:
542  * @obj: An #AtkObject
543  * @runtest: The callback function that is run when the "Run Tests"
544  *   button is clicked.
545  * @outwin: The output window to use.
546  *
547  * Creates the Test Select Window 
548  *
549  * Returns: TRUE if successful, FALSE otherwise
550  **/
551 static gboolean
552 _create_select_tests_window (AtkObject    *obj,
553                              TLruntest    runtest,
554                              OutputWindow **outwin)
555 {
556   GtkWidget *hbuttonbox;
557   GtkWidget *scrolledWindow;
558
559   if (window_no >= 0 && window_no < MAX_WINDOWS)
560     {
561       md[window_no] = (MainDialog *) malloc (sizeof(MainDialog));
562      
563       /* Setup Window */
564       md[window_no]->selecttestsTitle = "Test Setting";
565       md[window_no]->selecttestsWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
566       gtk_window_set_title (GTK_WINDOW( ow->outputWindow),
567                             md[window_no]->selecttestsTitle);
568       gtk_window_set_resizable (GTK_WINDOW(md[window_no]->selecttestsWindow),
569                                 FALSE);
570       gtk_window_set_position (GTK_WINDOW(md[window_no]->selecttestsWindow),
571                                GTK_WIN_POS_CENTER); 
572       g_signal_connect (md[window_no]->selecttestsWindow, 
573                         "destroy",
574                         G_CALLBACK (_destroy),
575                         &md[window_no]->selecttestsWindow);
576      
577       /* Setup Scrolling */
578       scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
579       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledWindow),
580                                       GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); 
581       gtk_widget_set_size_request (scrolledWindow, 500, 600);
582       gtk_container_add (GTK_CONTAINER (md[window_no]->selecttestsWindow), 
583                          scrolledWindow);
584       
585       /* Setup Layout */
586       md[window_no]->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
587       gtk_box_set_homogeneous (GTK_BOX (md[window_no]->vbox), TRUE);
588       md[window_no]->button = gtk_button_new_with_mnemonic ("_Run Tests");
589       hbuttonbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
590       gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox),
591                                  GTK_BUTTONBOX_SPREAD);
592       gtk_box_pack_end (GTK_BOX (hbuttonbox),
593                         GTK_WIDGET (md[window_no]->button), TRUE, TRUE, 0);
594       gtk_box_pack_end (GTK_BOX (md[window_no]->vbox), hbuttonbox,
595                         TRUE, TRUE, 0);
596       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolledWindow),
597                                              md[window_no]->vbox);
598
599       testcb[window_no].runtest = runtest;
600       testcb[window_no].obj = obj;
601       testcb[window_no].win_num = window_no; 
602       g_signal_connect (md[window_no]->button, 
603                         "clicked",
604                         G_CALLBACK (_testselectioncb),
605                         (gpointer)&testcb[window_no]);
606      
607       /* Show all */
608       gtk_widget_grab_focus (md[window_no]->button);
609       gtk_widget_show (md[window_no]->button);
610       gtk_widget_show (hbuttonbox); 
611       gtk_widget_show (scrolledWindow); 
612       gtk_widget_show_all (GTK_WIDGET (md[window_no]->selecttestsWindow));
613       return TRUE;
614     }
615   else
616     return FALSE;
617 }
618
619 /** 
620  * add_test
621  * @window: The window number
622  * @name: The test name
623  * @num_params: The number of arguments the test uses.
624  * @parameter_names: The names of each argument.
625  * @default_names: The default values of each argument.
626  *
627  * Adds a Test with the passed-in details to the Tests Select Window.  
628  *
629  * Returns: FALSE if the num_params passed in is greater than
630  * MAX_PARAMS, otherwise returns TRUE 
631  *
632  **/
633 gboolean
634 add_test (gint   window, 
635           gchar  *name,
636           gint   num_params,
637           gchar* parameter_names[],
638           gchar* default_names[])
639 {
640   gint i;
641
642   if (num_params > MAX_PARAMS)
643     return FALSE;
644   else
645     {
646       md[window]->hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
647       gtk_box_set_spacing (GTK_BOX (md[window]->hbox), 10);
648       gtk_container_set_border_width (GTK_CONTAINER (md[window]->hbox), 10);
649       gtk_container_add (GTK_CONTAINER (md[window]->vbox), md[window]->hbox);
650       listoftests[window][testcount[window]].toggleButton =
651          gtk_toggle_button_new_with_label (name);
652       gtk_box_pack_start (GTK_BOX (md[window]->hbox),
653           listoftests[window][testcount[window]].toggleButton, FALSE, FALSE, 0);
654       listoftests[window][testcount[window]].testName = name;
655       listoftests[window][testcount[window]].numParameters = num_params;
656       for (i=0; i<num_params; i++) 
657         {
658           listoftests[window][testcount[window]].parameterLabel[i] =
659             gtk_label_new (parameter_names[i]);
660           gtk_box_pack_start (GTK_BOX (md[window]->hbox),
661           listoftests[window][testcount[window]].parameterLabel[i], FALSE, FALSE, 0);
662           listoftests[window][testcount[window]].parameterInput[i] = gtk_entry_new();
663           gtk_entry_set_text (GTK_ENTRY (listoftests[window][testcount[window]].parameterInput[i]),
664             default_names[i]);
665           gtk_widget_set_size_request (listoftests[window][testcount[window]].parameterInput[i], 50, 22);
666           gtk_box_pack_start (GTK_BOX (md[window]->hbox),
667             listoftests[window][testcount[window]].parameterInput[i], FALSE, FALSE, 0);
668           gtk_widget_set_sensitive (
669             GTK_WIDGET (listoftests[window][testcount[window]].parameterLabel[i]), FALSE);
670           gtk_widget_set_sensitive (
671             GTK_WIDGET (listoftests[window][testcount[window]].parameterInput[i]), FALSE);
672           gtk_widget_show (listoftests[window][testcount[window]].parameterLabel[i]);
673           gtk_widget_show (listoftests[window][testcount[window]].parameterInput[i]);
674         }
675       g_signal_connect (listoftests[window][testcount[window]].toggleButton,
676                         "toggled",
677                         G_CALLBACK (_toggle_selectedcb),
678                         (gpointer)&(listoftests[window][testcount[window]]));
679       gtk_widget_show (listoftests[window][testcount[window]].toggleButton);
680       gtk_widget_show (md[window]->hbox);
681       gtk_widget_show (md[window]->vbox);
682
683       testcount[window]++;
684       counter++;
685       return TRUE;
686     }  
687 }
688
689 /** 
690  * tests_set:
691  * @window: The window number
692  * @count: Passes back the number of tests on.
693  *
694  * Gets an array of strings corresponding to the tests that are "on".
695  * A test is assumed on if the toggle button is on and if all its
696  * parameters have values.
697  *
698  * Returns: an array of strings corresponding to the tests that
699  * are "on".
700  **/
701 gchar **tests_set(gint window, int *count)
702 {
703   gint        i =0, j = 0, num;
704   gboolean    nullparam;
705   gchar*      input;
706
707   *count = 0;
708   for (i = 0; i < MAX_TESTS; i++)
709       onTests[window][i] = NULL;
710
711   for (i = 0; i < testcount[window]; i++)
712     {
713       nullparam = FALSE;
714       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (listoftests[window][i].toggleButton)))
715         {
716           num = listoftests[window][i].numParameters;
717           for (j = 0; j < num; j++)
718             {
719               input = gtk_editable_get_chars (
720                     GTK_EDITABLE (listoftests[window][i].parameterInput[j]), 0, -1);
721
722               if (input != NULL && (! strcmp(input, "")))
723                 nullparam = TRUE;
724             } 
725           if (!nullparam)
726             {
727               onTests[window][*count] = listoftests[window][i].testName;
728               *count = *count + 1; 
729             }
730         }
731     } 
732   return onTests[window];
733 }
734
735 /**
736  * _get_position_in_array:
737  * @window: The window number
738  * @the_test_name: The name of the test
739  *
740  * Gets the index of the passed-in @the_test_name.
741  *
742  * Returns: the position in listoftests[] of @the_test_name
743  **/
744 static gint
745 _get_position_in_array(gint  window,
746                        gchar *the_test_name)
747 {
748   gint        i;
749   
750   for (i = 0; i < testcount[window]; i++)
751     {
752       if (strcmp(listoftests[window][i].testName, the_test_name) == 0)
753         return i;
754     }
755   return -1;
756 }
757
758 /**
759  * _get_position_in_parameters:
760  * @window: The window number
761  * @label: The label name
762  * @position: The parameter position
763  *
764  * Gets the index of the passed-in parameter @label.
765  *
766  * Returns: the position in parameterLabel[] (a member of
767  * listoftests[]) of @label 
768  **/
769 static gint
770 _get_position_in_parameters(gint  window,
771                             gchar *label,
772                             gint  position)
773 {
774   gint                    i;
775   const gchar    *label_string;
776   
777   for (i = 0; i < MAX_PARAMS; i++)
778     {
779       label_string = gtk_label_get_text( 
780                GTK_LABEL (listoftests[window][position].parameterLabel[i]));
781
782       if (strcmp(label_string, label) == 0)
783         return i;
784     }
785   return -1;
786 }
787
788 /** 
789  * set_output_buffer:
790  * @output: The string to add to the output buffer
791  * 
792  * Tidies up the output Window 
793  **/
794 void
795 set_output_buffer(gchar *output)
796 {
797   gtk_text_buffer_insert (GTK_TEXT_BUFFER (ow->outputBuffer),
798                           &ow->outputIter, output, strlen(output));
799   gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (ow->outputBuffer),
800                                       &ow->outputIter, 0);
801 }
802
803 /**
804  * isVisibleDialog:
805  *
806  * Informs user if a visible test window running.
807  *
808  * Returns: TRUE if g_visibleDialog is set to 1, otherwise FALSE
809  **/
810 gboolean
811 isVisibleDialog(void)
812 {
813  if (g_visibleDialog >= 1)
814    return TRUE;
815  else
816    return FALSE;
817 }
818
819 /**
820  * get_arg_of_func:
821  * @window: The window number
822  * @function_name: The name of the function
823  * @arg_label: The label of the argument.
824  *
825  * Gets the user input associated with the @function_name and @arg_label.
826  *
827  * Returns: the user input associated with the @function_name and @arg_label.
828  **/
829 gchar*
830 get_arg_of_func (gint  window,
831                  gchar *function_name,
832                  gchar *arg_label)
833 {
834   const gchar       *argString;
835   gchar                      *retString;
836   gint                       position, paramPosition;
837
838   position =  _get_position_in_array(window, function_name);
839
840   if (position == -1)
841     {
842       g_print("No such function\n");
843       return NULL;
844     }
845
846   paramPosition = _get_position_in_parameters(window, arg_label, position);
847
848   if (paramPosition == -1)
849     {
850       g_print("No such parameter Label\n");
851       return NULL;
852     }
853
854   if (position != -1 && paramPosition != -1)
855     {
856       argString = gtk_editable_get_chars (
857         GTK_EDITABLE (listoftests[window][position].parameterInput[paramPosition]),
858       0, -1);
859       retString = g_strdup(argString);
860     }
861   else
862     retString = NULL;
863
864   return retString;
865 }
866
867 /**
868  * string_to_int:
869  * @the_string: The string to convert
870  *
871  * Converts the passed-in string to an integer 
872  *
873  * Returns: An integer corresponding to @the_string.
874  **/
875 int
876 string_to_int (const char *the_string)
877 {
878   char *end_ptr;
879   double ret_val;
880   int int_ret_val; 
881
882   while (1)
883     {
884       ret_val = strtod( the_string, &end_ptr);
885       if (*end_ptr == '\0')
886         break;
887       else
888         printf("\nError: input must be a number\n");
889     }
890    
891   int_ret_val = (int) ret_val;
892   return (int_ret_val);
893 }
894
895 /** 
896  * _toggle_selectedcb:
897  * @widget: The ToggleButton widget
898  * @test: user data containing the TestList structure.
899  *
900  * Toggle Button Callback, activating the text entry fields 
901  **/
902 static void
903 _toggle_selectedcb (GtkWidget *widget,
904                     gpointer  test)
905 {
906   int i;
907   TestList *testlist = (TestList *) test;
908   gboolean toggled;
909   gboolean sensitive;
910   toggled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
911   if (toggled)
912     sensitive = TRUE;
913   else
914     sensitive = FALSE;
915
916   for (i=0; i < testlist->numParameters; i++)
917     {
918       gtk_widget_set_sensitive (GTK_WIDGET (testlist->parameterLabel[i]),
919                                 sensitive);
920       gtk_widget_set_sensitive (GTK_WIDGET (testlist->parameterInput[i]),
921                                 sensitive);
922     }
923 }
924
925 /* 
926  * _testselectioncb:
927  * widget: The Button widget
928  * data: The user data containing a TestCB structure
929  *
930  * Callback for when the "Run Tests" button is pressed 
931  **/
932 static void
933 _testselectioncb (GtkWidget *widget,
934                   gpointer data)
935 {
936   TestCB* local_testcb = (TestCB *)data;
937   local_testcb->runtest(local_testcb->obj, local_testcb->win_num);
938 }
939
940 /**
941  * _destroy:
942  * @widget: The GUI widget
943  * @data: User data, not used.
944  *
945  * Destroy Callback.
946  **/
947 static void
948 _destroy (GtkWidget *widget,
949           gpointer  data)
950 {
951   gtk_main_quit();
952 }
953