@@ -28,6 +28,7 @@ use crate::{
2828 adapter:: Adapter ,
2929 context:: { AppContext , Context } ,
3030 filters:: filter,
31+ text_attributes:: ATTRIBUTE_GETTERS ,
3132 util:: * ,
3233 Action as AtspiAction , Error , ObjectEvent , Property , Rect as AtspiRect , Result ,
3334} ;
@@ -1309,19 +1310,33 @@ impl PlatformNode {
13091310 } )
13101311 }
13111312
1312- pub fn text_attribute_value ( & self , _offset : i32 , _attribute_name : & str ) -> Result < String > {
1313- // TODO: Implement rich text.
1314- Err ( Error :: UnsupportedInterface )
1313+ pub fn text_attribute_value ( & self , offset : i32 , attribute_name : & str ) -> Result < String > {
1314+ self . resolve_for_text ( |node| {
1315+ let pos = text_position_from_offset ( & node, offset) . ok_or ( Error :: IndexOutOfRange ) ?;
1316+ Ok ( ATTRIBUTE_GETTERS
1317+ . get ( attribute_name)
1318+ . and_then ( |getter| ( * getter) ( pos. inner_node ( ) ) )
1319+ . unwrap_or_default ( ) )
1320+ } )
13151321 }
13161322
1317- pub fn text_attributes ( & self , _offset : i32 ) -> Result < ( HashMap < String , String > , i32 , i32 ) > {
1318- // TODO: Implement rich text.
1319- Err ( Error :: UnsupportedInterface )
1323+ pub fn text_attributes (
1324+ & self ,
1325+ offset : i32 ,
1326+ ) -> Result < ( HashMap < & ' static str , String > , i32 , i32 ) > {
1327+ self . text_attribute_run ( offset, false )
13201328 }
13211329
1322- pub fn default_text_attributes ( & self ) -> Result < HashMap < String , String > > {
1323- // TODO: Implement rich text.
1324- Err ( Error :: UnsupportedInterface )
1330+ pub fn default_text_attributes ( & self ) -> Result < HashMap < & ' static str , String > > {
1331+ self . resolve_for_text ( |node| {
1332+ let mut result = HashMap :: with_capacity ( ATTRIBUTE_GETTERS . len ( ) ) ;
1333+ for ( name, getter) in ATTRIBUTE_GETTERS . entries ( ) {
1334+ if let Some ( value) = ( * getter) ( & node) {
1335+ result. insert ( * name, value) ;
1336+ }
1337+ }
1338+ Ok ( result)
1339+ } )
13251340 }
13261341
13271342 pub fn character_extents ( & self , offset : i32 , coord_type : CoordType ) -> Result < AtspiRect > {
@@ -1469,14 +1484,41 @@ impl PlatformNode {
14691484
14701485 pub fn text_attribute_run (
14711486 & self ,
1472- _offset : i32 ,
1473- _include_defaults : bool ,
1474- ) -> Result < ( HashMap < String , String > , i32 , i32 ) > {
1475- // TODO: Implement rich text.
1476- // For now, just report a range spanning the entire text with no attributes,
1477- // this is required by Orca to announce selection content and caret movements.
1478- let character_count = self . character_count ( ) ?;
1479- Ok ( ( HashMap :: new ( ) , 0 , character_count) )
1487+ offset : i32 ,
1488+ include_defaults : bool ,
1489+ ) -> Result < ( HashMap < & ' static str , String > , i32 , i32 ) > {
1490+ self . resolve_for_text ( |node| {
1491+ let pos = text_position_from_offset ( & node, offset) . ok_or ( Error :: IndexOutOfRange ) ?;
1492+ let mut result = HashMap :: with_capacity ( ATTRIBUTE_GETTERS . len ( ) ) ;
1493+ for ( name, getter) in ATTRIBUTE_GETTERS . entries ( ) {
1494+ if let Some ( value) = ( * getter) ( pos. inner_node ( ) ) {
1495+ if !include_defaults {
1496+ if let Some ( default) = ( * getter) ( & node) {
1497+ if value == default {
1498+ continue ;
1499+ }
1500+ }
1501+ }
1502+ result. insert ( * name, value) ;
1503+ }
1504+ }
1505+ let start = if pos. is_format_start ( ) {
1506+ pos
1507+ } else {
1508+ pos. backward_to_format_start ( )
1509+ } ;
1510+ let end = pos. forward_to_format_end ( ) ;
1511+ Ok ( (
1512+ result,
1513+ start
1514+ . to_global_usv_index ( )
1515+ . try_into ( )
1516+ . map_err ( |_| Error :: TooManyCharacters ) ?,
1517+ end. to_global_usv_index ( )
1518+ . try_into ( )
1519+ . map_err ( |_| Error :: TooManyCharacters ) ?,
1520+ ) )
1521+ } )
14801522 }
14811523
14821524 pub fn scroll_substring_to (
0 commit comments