OSDN Git Service

Support reporting of text formatting in Mozilla Gecko (Firefox, Thunderbird, etc.).
authorJames Teh <jamie@jantrid.net>
Thu, 4 Aug 2011 02:43:14 +0000 (12:43 +1000)
committerJames Teh <jamie@jantrid.net>
Thu, 4 Aug 2011 02:43:14 +0000 (12:43 +1000)
Simplified the IA2 text scanning code in the Gecko vbuf backend in the process.
Fixes #394.

nvdaHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
source/virtualBuffers/gecko_ia2.py
user_docs/en/changes.t2t

index afc0655..d422d12 100755 (executable)
@@ -626,35 +626,48 @@ VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc, VBufSt
                //Look up the IAccessible2 objects at the positions of the embedded object chars\r
                //Add the text and IA2 objects in order to a vector for later adding to the buffer\r
                if(paccHypertext&&IA2Text!=NULL&&IA2TextLength>0&&!IA2TextIsUnneededSpace) {\r
-               LOG_DEBUG(L"scanning text for embedded object chars");\r
-                       int textStart=-1;\r
-                       wchar_t* tempText=NULL;\r
-                       for(int i=0;i<IA2TextLength;++i) {\r
-                               LOG_DEBUG(L"offset "<<i);\r
-                               if(IA2Text[i]!=0xfffc) { //is not an embeded object char\r
-                                       LOG_DEBUG(L"normal char");\r
-                                       if(tempText==NULL) {\r
-                                               textStart=i;\r
-                                               LOG_DEBUG(L"allocating new tempText memory to hold "<<((IA2TextLength+1)-i)<<L" chars");\r
-                                               tempText=(wchar_t*)malloc(sizeof(wchar_t)*((IA2TextLength+1)-i));\r
-                                               if(tempText==NULL) {\r
-                                                       LOG_DEBUG(L"Error allocating tempText memory");\r
-                                                       return NULL;\r
-                                               }\r
+               LOG_DEBUG(L"scanning text");\r
+                       int chunkStart=0;\r
+                       long attribsStart = 0;\r
+                       long attribsEnd = 0;\r
+                       map<wstring,wstring> textAttribs;\r
+                       for(int i=0;;++i) {\r
+                               if(i!=chunkStart&&(i==IA2TextLength||i==attribsEnd||IA2Text[i]==0xfffc)) {\r
+                                       // We've reached the end of the current chunk of text.\r
+                                       // (A chunk ends at the end of the text, at the end of an attributes run\r
+                                       // or at an embedded object char.)\r
+                                       // Add the chunk to the buffer.\r
+                                       LOG_DEBUG("Adding text chunk, start="<<chunkStart<<" end="<<i);\r
+                                       if((tempNode=buffer->addTextFieldNode(parentNode,previousNode,wstring(IA2Text+chunkStart,i-chunkStart)))!=NULL) {\r
+                                               previousNode=tempNode;\r
+                                               // Add text attributes.\r
+                                               for(map<wstring,wstring>::const_iterator it=textAttribs.begin();it!=textAttribs.end();++it)\r
+                                                       previousNode->addAttribute(it->first,it->second);\r
                                        }\r
-                                       tempText[i-textStart]=IA2Text[i];\r
-                               } else { //is an embedded object char\r
-                                       LOG_DEBUG(L"is an embedded object char");\r
-                                       if(tempText!=NULL) {\r
-                                               LOG_DEBUG(L"there is tempText, terminate it with NULL");\r
-                                               tempText[i-textStart]=L'\0';\r
-                                               LOG_DEBUG(L"adding tempText of length "<<(i-textStart)+1<<L" to buffer");\r
-                                               if((tempNode=buffer->addTextFieldNode(parentNode,previousNode,tempText))!=NULL) {\r
-                                                       previousNode=tempNode;\r
+                               }\r
+                               if(i==IA2TextLength)\r
+                                       break;\r
+                               if(i==attribsEnd) {\r
+                                       // We've hit the end of the last attributes run and thus the start of the next.\r
+                                       textAttribs.clear();\r
+                                       chunkStart=i;\r
+                                       BSTR attribsStr;\r
+                                       if(paccText->get_attributes(attribsEnd,&attribsStart,&attribsEnd,&attribsStr)==S_OK) {\r
+                                               LOG_DEBUG("Start of new attributes run at "<<i);\r
+                                               if(attribsStr) {\r
+                                                       IA2AttribsToMap(attribsStr,textAttribs);\r
+                                                       SysFreeString(attribsStr);\r
                                                }\r
-                                               free(tempText);\r
-                                               tempText=NULL;\r
+                                       } else {\r
+                                               // If attributes fails, assume it'll fail for the entire text.\r
+                                               attribsEnd=IA2TextLength;\r
                                        }\r
+                               }\r
+                               if(IA2Text[i]==0xfffc) {\r
+                                       // Embedded object char.\r
+                                       LOG_DEBUG(L"embedded object char at "<<i);\r
+                                       // The next chunk of text shouldn't include this char.\r
+                                       chunkStart=i+1;\r
                                        LOG_DEBUG(L"get hyperlinkIndex with IAccessibleHypertext::get_hyperlinkIndex and offset "<<i);\r
                                        int hyperlinkIndex;\r
                                        if((res=paccHypertext->get_hyperlinkIndex(i,(long*)(&hyperlinkIndex)))!=S_OK) {\r
@@ -703,14 +716,6 @@ VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc, VBufSt
                                }\r
                        }\r
                        LOG_DEBUG(L"End of scan");\r
-                       if(tempText!=NULL) {\r
-                               LOG_DEBUG(L"some tempText left, terminate with NULL");\r
-                               tempText[IA2TextLength-textStart]=L'\0';\r
-                               LOG_DEBUG(L"add tempText of length "<<(IA2TextLength-textStart)+1<<L" to buffer");\r
-                               previousNode=buffer->addTextFieldNode(parentNode,previousNode,tempText);\r
-                               free(tempText);\r
-                               tempText=NULL;\r
-                       }\r
                } else  if(IA2TextLength>0&&!IA2TextIsUnneededSpace) {\r
                        LOG_DEBUG(L"add IA2Text to childVector");\r
                        if((tempNode=buffer->addTextFieldNode(parentNode,previousNode,IA2Text))!=NULL) {\r
index 7b45fbb..931041d 100755 (executable)
@@ -12,6 +12,7 @@ from comtypes.gen.IAccessible2Lib import IAccessible2
 from comtypes import COMError\r
 import aria\r
 import config\r
+from NVDAObjects.IAccessible import normalizeIA2TextFormatField\r
 \r
 class Gecko_ia2_TextInfo(VirtualBufferTextInfo):\r
 \r
@@ -56,6 +57,10 @@ class Gecko_ia2_TextInfo(VirtualBufferTextInfo):
                        attrs["landmark"]=landmark\r
                return super(Gecko_ia2_TextInfo,self)._normalizeControlField(attrs)\r
 \r
+       def _normalizeFormatField(self, attrs):\r
+               normalizeIA2TextFormatField(attrs)\r
+               return attrs\r
+\r
 class Gecko_ia2(VirtualBuffer):\r
 \r
        TextInfo=Gecko_ia2_TextInfo\r
index 0e0e815..74715d6 100644 (file)
@@ -7,6 +7,7 @@
 \r
 == New Features ==\r
 - In Mozilla Gecko (e.g. Firefox) Heading levels are now announced  when using object navigation.\r
+- Text formatting can now be reported when using browse mode in Mozilla Gecko (e.g. Firefox and Thunderbird). (#394)\r
 \r
 \r
 == Bug Fixes ==\r