static void test_application (Accessible *application) { char *str; fprintf (stderr, "Testing application ...\n"); g_assert (Accessible_isApplication (application)); g_assert (Accessible_getApplication (application) == application); AccessibleApplication_unref (application); str = AccessibleApplication_getToolkitName (application); g_assert (str != NULL); g_assert (!strcmp (str, "GAIL")); SPI_freeString (str); str = AccessibleApplication_getLocale (application, LC_MESSAGES); g_assert (!strcmp (str, setlocale (LC_MESSAGES, NULL))); SPI_freeString (str); str = AccessibleApplication_getVersion (application); g_assert (str != NULL); SPI_freeString (str); AccessibleApplication_getID (application); }
static void test_editable_text (AccessibleEditableText *etext) { char *str; AccessibleText *text; fprintf (stderr, "Testing editable text ...\n"); g_assert (Accessible_isText (etext)); text = Accessible_getText (etext); AccessibleEditableText_setTextContents ( etext, TEST_STRING_B); str = AccessibleText_getText (text, 0, WHOLE_STRING); g_assert (!strcmp (str, TEST_STRING_B)); SPI_freeString (str); /* FIXME: lots more editing here */ AccessibleEditableText_setTextContents ( etext, TEST_STRING_A); AccessibleText_unref (text); }
static void restartTerm(Accessible *newTerm, AccessibleText *newTextTerm) { char *c,*d; const char *e; long i,len; char *text; if (curFocus) finiTerm(); Accessible_ref(curFocus = newTerm); curTerm = newTextTerm; logMessage(LOG_DEBUG,"new term %p",curTerm); text = AccessibleText_getText(curTerm,0,LONG_MAX); curNumRows = 0; if (curRows) { for (i=0;i<curNumRows;i++) free(curRows[i]); free(curRows); } free(curRowLengths); c = text; while (*c) { curNumRows++; if (!(c = strchr(c,'\n'))) break; c++; } logMessage(LOG_DEBUG,"%ld rows",curNumRows); curRows = malloc(curNumRows * sizeof(*curRows)); curRowLengths = malloc(curNumRows * sizeof(*curRowLengths)); i = 0; curNumCols = 0; for (c = text; *c; c = d+1) { d = strchr(c,'\n'); if (d) *d = 0; e = c; curRowLengths[i] = (len = my_mbsrtowcs(NULL,&e,0,NULL)) + (d != NULL); if (len > curNumCols) curNumCols = len; else if (len < 0) { if (len==-2) logMessage(LOG_ERR,"unterminated sequence %s",c); else if (len==-1) logSystemError("mbrlen"); curRowLengths[i] = (len = -1) + (d != NULL); } curRows[i] = malloc((len + (d!=NULL)) * sizeof(*curRows[i])); e = c; my_mbsrtowcs(curRows[i],&e,len,NULL); if (d) curRows[i][len]='\n'; else break; i++; } logMessage(LOG_DEBUG,"%ld cols",curNumCols); SPI_freeString(text); caretPosition(AccessibleText_getCaretOffset(curTerm)); }
static void log_accessible (EventLog *log, Accessible *accessible) { GtkTextTag *tag; GtkTextIter iter; char *text, *name, *descr, *short_descr; char *role_name, *ifaces; if (!accessible) { log_message (log, "<Null>"); return; } tag = gtk_text_buffer_create_tag (log->log_text, NULL, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); Accessible_ref (accessible); g_object_set_data_full (G_OBJECT (tag), "accessible", accessible, (GDestroyNotify) Accessible_unref ); ifaces = accessible_get_iface_string (accessible); role_name = Accessible_getRoleName (accessible); name = Accessible_getName (accessible); descr = Accessible_getDescription (accessible); short_descr = ellipsize (descr); /* FIXME: nice mangled printout of supported interfaces ? */ text = g_strdup_printf ("%s:%s:%s:%s", ifaces, role_name ? role_name : "--", name ? name : "--", short_descr ? short_descr : "--"); gtk_text_buffer_get_end_iter (log->log_text, &iter); gtk_text_buffer_insert_with_tags (log->log_text, &iter, text, -1, tag, NULL); g_free (text); g_free (short_descr); SPI_freeString (descr); SPI_freeString (name); SPI_freeString (role_name); g_free (ifaces); log_track_end (log); }
static void control_spi_listener_build_actions_list (ControlSpiListener *listener, Accessible *parent, int depth) { Accessible* child; AccessibleRole role; int i, child_count; if (depth > SEARCH_DEPTH) return; child_count = Accessible_getChildCount (parent); child_count = MIN (child_count, SEARCH_BREADTH); for (i = 0; i < child_count; ++i) { char *name; char *normalized_name; child = Accessible_getChildAtIndex (parent, i); if (child == parent) continue; name = Accessible_getName (child); #if DEBUG { gchar *role_name; role_name = Accessible_getRoleName (child); g_message ("Looking at %s %s", role_name, name); } #endif if (name) { normalized_name = control_spi_listener_normalize (name); if (normalized_name && strlen(normalized_name) > 0 && is_actionable (child)) { AccessibleItem *item; item = g_new0(AccessibleItem, 1); Accessible_ref (child); item->accessible = child; item->name = g_strdup (normalized_name); listener->actions = g_slist_append (listener->actions, item); } SPI_freeString (name); g_free (normalized_name); } if (is_worth_searching (child)) control_spi_listener_build_actions_list (listener, child, depth+1); Accessible_unref (child); } }
static void stream_cache_item_free (gpointer a) { struct StreamCacheItem *cache_item = a; cspi_release_unref (cache_item->stream); SPI_freeString (cache_item->mimetype); g_free (cache_item); }
static void test_misc (void) { fprintf (stderr, "Testing misc bits ...\n"); g_assert (!Accessible_isComponent (NULL)); g_assert (Accessible_getComponent (NULL) == NULL); SPI_freeString (NULL); }
void log_object_property_change (EventLog *log, const AccessibleEvent *event) { char *detail; if (!log_sanity_check (log, event, SANITY_NOCHECK_SOURCE) ) return; { char **split = g_strsplit (event->type, ":", -1); if (split && split[0] && split[1] && split[2]) detail = g_strdup (split[2]); else detail = g_strdup (""); g_strfreev (split); } if (!strcmp (detail, "accessible-name")) { char *text = AccessibleNameChangedEvent_getNameString (event); log_string_prop_change (log, event, "name", text); SPI_freeString (text); } else if (!strcmp (detail, "accessible-description")) { char *text = AccessibleDescriptionChangedEvent_getDescriptionString (event); log_string_prop_change (log, event, "description", text); SPI_freeString (text); } else if (!strcmp (detail, "accessible-parent")) { Accessible *parent = AccessibleParentChangedEvent_getParentAccessible (event); log_message (log, "parent change %d %d on ", event->detail1, event->detail2); log_accessible (log, event->source); log_message (log, " to parent: "); log_accessible (log, parent); log_message (log, "\n"); Accessible_unref (parent); } else { log_message (log, "generic property change (%s) %d %d on ", event->type, event->detail1, event->detail2); log_accessible (log, event->source); log_message (log, "\n"); } g_free (detail); }
static void check_for_matching_frame( Driver* dp, Accessible* accessible ) { int role = Accessible_getRole( accessible ); if ( role == SPI_ROLE_FRAME ) { char* frame_name = Accessible_getName( accessible ); if ( strcmp(frame_name, dp->application_title) == 0 ) { dp->frame = accessible; dp->found_application = TRUE; } SPI_freeString( frame_name ); } }
static gboolean eval_func (Accessible *a, gpointer data) { gboolean found; char *name; name = Accessible_getName (a); found = g_str_equal (name, "Window List"); SPI_freeString (name); return found; }
static void test_action (AccessibleAction *action) { gint n_actions, i; gchar *s, *sd; g_assert ((n_actions = AccessibleAction_getNActions (action)) >= 0); fprintf (stderr, "Testing actions..."); for (i = 0; i < n_actions; ++i) { s = AccessibleAction_getName (action, i); g_assert (s); sd = AccessibleAction_getDescription (action, i); g_assert (sd); fprintf (stderr, "%d: %s (%s); ", i, s, sd); SPI_freeString (s); SPI_freeString (sd); g_assert (AccessibleAction_doAction (action, i)); } fprintf (stderr, "\n"); }
static void test_text (AccessibleText *text) { char *str; fprintf (stderr, "Testing text ...\n"); g_assert (AccessibleText_getCharacterCount (text) == strlen (TEST_STRING_A)); str = AccessibleText_getText (text, 0, WHOLE_STRING); g_assert (!strcmp (str, TEST_STRING_A)); SPI_freeString (str); str = AccessibleText_getText (text, 0, 5); g_assert (!strncmp (str, TEST_STRING_A, 5)); SPI_freeString (str); AccessibleText_setCaretOffset (text, 7); g_assert (AccessibleText_getCaretOffset (text) == 7); /* FIXME: lots more tests - selections etc. etc. */ }
void log_object_text_changed (EventLog *log, const AccessibleEvent *event) { char *text; if (!log_sanity_check_text (log, event)) return; log_message (log, "text changed (%s) offset %d length %d on ", event->type, event->detail1, event->detail2); log_accessible (log, event->source); text = AccessibleTextChangedEvent_getChangeString (event); log_message (log, " change string '%s'", text ? text : "<null>"); SPI_freeString (text); }
static SPIBoolean exception_handler( SPIException* err, SPIBoolean is_fatal ) { // We wish to swallow a non-fatal error... if ( is_fatal ) return FALSE; // We haven't dealt with it. // ...which has a specific description. char* description = SPIException_getDescription( err ); int result = strcmp( description, "IDL:omg.org/CORBA/COMM_FAILURE:1.0" ); SPI_freeString( description ); if ( result != 0 ) return FALSE; // We haven't dealt with it. else return TRUE; // We have dealt with it -- ie ignore it. }
static void test_image (AccessibleImage *image) { char *desc; long int x = -1, y = -1, width = -1, height = -1; desc = AccessibleImage_getImageDescription (image); g_assert (desc != NULL); SPI_freeString (desc); AccessibleImage_getImagePosition (image, &x, &y, SPI_COORD_TYPE_SCREEN); AccessibleImage_getImageSize (image, &width, &height); AccessibleImage_getImageExtents (image, &x, &y, &width, &height, SPI_COORD_TYPE_WINDOW); }
void log_object_text_selection_changed (EventLog *log, const AccessibleEvent *event) { char *text; if (!log_sanity_check_text (log, event)) return; /* FIXME: more detail on the details */ log_message (log, "text selection changed (%s) %d %d on ", event->type, event->detail1, event->detail2); log_accessible (log, event->source); text = AccessibleTextSelectionChangedEvent_getSelectionString (event); log_message (log, "context '%s'\n", text); SPI_freeString (text); }
void log_window (EventLog *log, const AccessibleEvent *event) { char *title; if (!log_sanity_check (log, event, SANITY_CHECK_SOURCE) ) return; log_message (log, "window event '%s' (%d) (%d) on ", event->type, event->detail1, event->detail2); log_accessible (log, event->source); title = AccessibleWindowEvent_getTitleString (event); log_message (log, " with title '%s'\n", title ? title : "<Null>"); SPI_freeString (title); }
static void report_leaked_ref (gpointer key, gpointer val, gpointer user_data) { char *name, *role; Accessible *a = (Accessible *) val; name = Accessible_getName (a); if (cspi_exception ()) { name = NULL; } role = Accessible_getRoleName (a); if (cspi_exception ()) { role = NULL; } fprintf (stderr, "leaked %d references to object %s, role %s %p\n", a->ref_count, name ? name : "<?>", role ? role : "<?>", a); SPI_freeString (name); }
static void validate_accessible (Accessible *accessible, gboolean has_parent, gboolean recurse_down) { Accessible *tmp; char *name, *descr; AccessibleRole role; AccessibleRelation **relations; char *role_name; GString *item_str = g_string_new (""); int i; name = Accessible_getName (accessible); g_assert (name != NULL); descr = Accessible_getDescription (accessible); g_assert (descr != NULL); role = Accessible_getRole (accessible); g_assert (role != SPI_ROLE_INVALID); role_name = Accessible_getRoleName (accessible); g_assert (role_name != NULL); relations = Accessible_getRelationSet (accessible); g_assert (relations != NULL); for (i = 0; relations [i]; i++) { AccessibleRelationType type; int targets; fprintf (stderr, "relation %d\n", i); type = AccessibleRelation_getRelationType (relations [i]); g_assert (type != SPI_RELATION_NULL); targets = AccessibleRelation_getNTargets (relations [i]); g_assert (targets != -1); AccessibleRelation_unref (relations [i]); relations [i] = NULL; } free (relations); if (print_tree) { int i; for (i = 0; i < print_tree_depth; i++) fputc (' ', stderr); fputs ("|-> [ ", stderr); } if (Accessible_isAction (accessible)) { tmp = Accessible_getAction (accessible); g_assert (tmp != NULL); if (print_tree) fprintf (stderr, "At"); else test_action (tmp); AccessibleAction_unref (tmp); } if (Accessible_isApplication (accessible)) { tmp = Accessible_getApplication (accessible); if (print_tree) fprintf (stderr, "Ap"); else test_application (tmp); AccessibleApplication_unref (tmp); } if (Accessible_isComponent (accessible)) { tmp = Accessible_getComponent (accessible); g_assert (tmp != NULL); if (print_tree) fprintf (stderr, "Co"); else test_component (tmp); AccessibleComponent_unref (tmp); } if (Accessible_isEditableText (accessible)) { tmp = Accessible_getEditableText (accessible); g_assert (tmp != NULL); if (print_tree) fprintf (stderr, "Et"); else test_editable_text (tmp); AccessibleEditableText_unref (tmp); } if (Accessible_isHypertext (accessible)) { tmp = Accessible_getHypertext (accessible); g_assert (tmp != NULL); if (print_tree) fprintf (stderr, "Ht"); AccessibleHypertext_unref (tmp); } if (Accessible_isImage (accessible)) { tmp = Accessible_getImage (accessible); g_assert (tmp != NULL); if (print_tree) { char *desc; fprintf (stderr, "Im"); desc = AccessibleImage_getImageDescription (tmp); g_string_append_printf ( item_str, " image descr: '%s'", desc); SPI_freeString (desc); } else test_image (tmp); AccessibleImage_unref (tmp); } if (Accessible_isSelection (accessible)) { tmp = Accessible_getSelection (accessible); g_assert (tmp != NULL); if (print_tree) fprintf (stderr, "Se"); AccessibleSelection_unref (tmp); } if (Accessible_isTable (accessible)) { tmp = Accessible_getTable (accessible); g_assert (tmp != NULL); if (print_tree) fprintf (stderr, "Ta"); else test_table (tmp); AccessibleTable_unref (tmp); } if (Accessible_isText (accessible)) { tmp = Accessible_getText (accessible); g_assert (tmp != NULL); if (print_tree) fprintf (stderr, "Te"); else { if (strcmp (name, TEST_STRING_A_OBJECT) == 0) test_text (tmp); } AccessibleText_unref (tmp); } if (Accessible_isValue (accessible)) { tmp = Accessible_getValue (accessible); g_assert (tmp != NULL); if (print_tree) fprintf (stderr, "Va"); else test_value (tmp); AccessibleValue_unref (tmp); } if (print_tree) fprintf (stderr, " ] '%s' (%s) - %s: %s\n", name, descr, role_name, item_str->str); SPI_freeString (name); SPI_freeString (descr); SPI_freeString (role_name); g_string_free (item_str, TRUE); validate_tree (accessible, has_parent, recurse_down); }
static void evListenerCB(const AccessibleEvent *event, void *user_data) { static int running = 0; struct evList *ev = malloc(sizeof(*ev)); AccessibleEvent_ref(event); AccessibleText *newText; ev->next = evs; ev->ev = event; evs = ev; int state_changed_focused; /* this is not atomic but we can only be recursively called within calls * to the lib */ if (running) return; else running = 1; while (evs) { pthread_mutex_lock(&updateMutex); /* pickup a list of events to handle */ ev = evs; evs = NULL; for (; ev; AccessibleEvent_unref(ev->ev), ev = ev->next) { event = ev->ev; state_changed_focused = !strcmp(event->type,"object:state-changed:focused"); if (state_changed_focused && !event->detail1) { if (event->source == curFocus) finiTerm(); } else if (!strcmp(event->type,"focus:") || (state_changed_focused && event->detail1)) { if (!(newText = Accessible_getText(event->source))) { if (curFocus) finiTerm(); } else { AccessibleRole role = Accessible_getRole(event->source); if (typeAll || (typeText && ((role == SPI_ROLE_TEXT) || (role == SPI_ROLE_PASSWORD_TEXT) || (role == SPI_ROLE_PARAGRAPH))) || (typeTerminal && (role == SPI_ROLE_TERMINAL))) { restartTerm(event->source, newText); } else { logMessage(LOG_DEBUG,"AT SPI widget not for us"); if (curFocus) finiTerm(); } } } else if (!strcmp(event->type,"object:text-caret-moved")) { if (event->source != curFocus) continue; logMessage(LOG_DEBUG,"caret move to %lu",event->detail1); caretPosition(event->detail1); } else if (!strcmp(event->type,"object:text-changed:delete")) { long x,y,toDelete = event->detail2; long length = 0, toCopy; long downTo; /* line that will provide what will follow x */ logMessage(LOG_DEBUG,"delete %lu from %lu",event->detail2,event->detail1); if (event->source != curFocus) continue; findPosition(event->detail1,&x,&y); downTo = y; if (downTo < curNumRows) length = curRowLengths[downTo]; while (x+toDelete >= length) { downTo++; if (downTo <= curNumRows - 1) length += curRowLengths[downTo]; else { /* imaginary extra line doesn't provide more length, and shouldn't need to ! */ if (x+toDelete > length) { logMessage(LOG_ERR,"deleting past end of text !"); /* discarding */ toDelete = length - x; } break; /* deleting up to end */ } } if (length-toDelete>0) { /* still something on line y */ if (y!=downTo) { curRowLengths[y] = length-toDelete; curRows[y]=realloc(curRows[y],curRowLengths[y]*sizeof(*curRows[y])); } if ((toCopy = length-toDelete-x)) memmove(curRows[y]+x,curRows[downTo]+curRowLengths[downTo]-toCopy,toCopy*sizeof(*curRows[downTo])); if (y==downTo) { curRowLengths[y] = length-toDelete; curRows[y]=realloc(curRows[y],curRowLengths[y]*sizeof(*curRows[y])); } } else { /* kills this line as well ! */ y--; } if (downTo>=curNumRows) /* imaginary extra lines don't need to be deleted */ downTo=curNumRows-1; delRows(y+1,downTo-y); caretPosition(AccessibleText_getCaretOffset(curTerm)); } else if (!strcmp(event->type,"object:text-changed:insert")) { long len=event->detail2,semilen,x,y; char *added; const char *adding,*c; logMessage(LOG_DEBUG,"insert %lu from %lu",event->detail2,event->detail1); if (event->source != curFocus) continue; findPosition(event->detail1,&x,&y); adding = c = added = AccessibleTextChangedEvent_getChangeString(event); if (x && (c = strchr(adding,'\n'))) { /* splitting line */ addRows(y,1); semilen=my_mbslen(adding,c+1-adding); curRowLengths[y]=x+semilen; if (x+semilen-1>curNumCols) curNumCols=x+semilen-1; /* copy beginning */ curRows[y]=malloc(curRowLengths[y]*sizeof(*curRows[y])); memcpy(curRows[y],curRows[y+1],x*sizeof(*curRows[y])); /* add */ my_mbsrtowcs(curRows[y]+x,&adding,semilen,NULL); len-=semilen; adding=c+1; /* shift end */ curRowLengths[y+1]-=x; memmove(curRows[y+1],curRows[y+1]+x,curRowLengths[y+1]*sizeof(*curRows[y+1])); x=0; y++; } while ((c = strchr(adding,'\n'))) { /* adding lines */ addRows(y,1); semilen=my_mbslen(adding,c+1-adding); curRowLengths[y]=semilen; if (semilen-1>curNumCols) curNumCols=semilen-1; curRows[y]=malloc(semilen*sizeof(*curRows[y])); my_mbsrtowcs(curRows[y],&adding,semilen,NULL); len-=semilen; adding=c+1; y++; } if (len) { /* still length to add on the line following it */ if (y==curNumRows) { /* It won't insert ending \n yet */ addRows(y,1); curRows[y]=NULL; curRowLengths[y]=0; } curRowLengths[y] += len; curRows[y]=realloc(curRows[y],curRowLengths[y]*sizeof(*curRows[y])); memmove(curRows[y]+x+len,curRows[y]+x,(curRowLengths[y]-(x+len))*sizeof(*curRows[y])); my_mbsrtowcs(curRows[y]+x,&adding,len,NULL); if (curRowLengths[y]-(curRows[y][curRowLengths[y]-1]=='\n')>curNumCols) curNumCols=curRowLengths[y]-(curRows[y][curRowLengths[y]-1]=='\n'); } SPI_freeString(added); caretPosition(AccessibleText_getCaretOffset(curTerm)); } else logMessage(LOG_INFO,"event %s, source %p, detail1 %lu detail2 %lu",event->type,event->source,event->detail1,event->detail2); } pthread_mutex_unlock(&updateMutex); } running = 0; }
char * windows_string ( char * _str ) { char * ret = SQ_STRDUP_FUNCTION(_str); SPI_freeString ( _str ); return ret; }