Skip to content

Commit

Permalink
MS Word support: add support for newer style form fields (content con…
Browse files Browse the repository at this point in the history
…trols). Re #2295.
  • Loading branch information
michaelDCurran committed Aug 8, 2013
1 parent 1e7c015 commit 0f97a66
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 15 deletions.
41 changes: 36 additions & 5 deletions nvdaHelper/remote/winword.cpp
Expand Up @@ -50,11 +50,17 @@ using namespace std;
#define wdDISPID_RANGE_LANGUAGEID 153
#define wdDISPID_RANGE_DUPLICATE 6
#define wdDISPID_RANGE_FORMFIELDS 65
#define wdDISPID_RANGE_CONTENTCONTROLS 424
#define wdDISPID_FORMFIELDS_ITEM 0
#define wdDISPID_FORMFIELD_RANGE 17
#define wdDISPID_FORMFIELD_TYPE 0
#define wdDISPID_FORMFIELD_RESULT 10
#define wdDISPID_FORMFIELD_STATUSTEXT 8
#define wdDISPID_CONTENTCONTROLS_ITEM 0
#define wdDISPID_CONTENTCONTROL_RANGE 1
#define wdDISPID_CONTENTCONTROL_TYPE 5
#define wdDISPID_CONTENTCONTROL_CHECKED 28
#define wdDISPID_CONTENTCONTROL_TITLE 12
#define wdDISPID_STYLE_NAMELOCAL 0
#define wdDISPID_RANGE_SPELLINGERRORS 316
#define wdDISPID_SPELLINGERRORS_COUNT 1
Expand Down Expand Up @@ -207,12 +213,10 @@ BOOL generateFormFieldXML(IDispatch* pDispatchRange, wostringstream& XMLStream,
return false;
}
_com_dispatch_raw_method(pDispatchRange2,wdDISPID_RANGE_EXPAND,DISPATCH_METHOD,VT_EMPTY,NULL,L"\x0003",wdParagraph,1);
IDispatchPtr pDispatchFormFields=NULL;
if(_com_dispatch_raw_propget(pDispatchRange2,wdDISPID_RANGE_FORMFIELDS,VT_DISPATCH,&pDispatchFormFields)!=S_OK||!pDispatchFormFields) {
return false;
}
BOOL foundFormField=false;
for(int count=1;!foundFormField&&count<100;++count) {
IDispatchPtr pDispatchFormFields=NULL;
_com_dispatch_raw_propget(pDispatchRange2,wdDISPID_RANGE_FORMFIELDS,VT_DISPATCH,&pDispatchFormFields);
if(pDispatchFormFields) for(int count=1;!foundFormField&&count<100;++count) {
IDispatchPtr pDispatchFormField=NULL;
if(_com_dispatch_raw_method(pDispatchFormFields,wdDISPID_FORMFIELDS_ITEM,DISPATCH_METHOD,VT_DISPATCH,&pDispatchFormField,L"\x0003",count)!=S_OK||!pDispatchFormField) {
break;
Expand All @@ -237,6 +241,33 @@ BOOL generateFormFieldXML(IDispatch* pDispatchRange, wostringstream& XMLStream,
_com_dispatch_raw_propput(pDispatchRange,wdDISPID_RANGE_END,VT_I4,chunkEnd);
break;
}
if(foundFormField) return true;
IDispatchPtr pDispatchContentControls=NULL;
_com_dispatch_raw_propget(pDispatchRange2,wdDISPID_RANGE_CONTENTCONTROLS,VT_DISPATCH,&pDispatchContentControls);
if(pDispatchContentControls)for(int count=1;!foundFormField&&count<100;++count) {
IDispatchPtr pDispatchContentControl=NULL;
if(_com_dispatch_raw_method(pDispatchContentControls,wdDISPID_CONTENTCONTROLS_ITEM,DISPATCH_METHOD,VT_DISPATCH,&pDispatchContentControl,L"\x0003",count)!=S_OK||!pDispatchContentControl) {
break;
}
IDispatchPtr pDispatchContentControlRange=NULL;
if(_com_dispatch_raw_propget(pDispatchContentControl,wdDISPID_CONTENTCONTROL_RANGE,VT_DISPATCH,&pDispatchContentControlRange)!=S_OK||!pDispatchContentControlRange) {
break;
}
if(_com_dispatch_raw_method(pDispatchRange,wdDISPID_RANGE_INRANGE,DISPATCH_METHOD,VT_BOOL,&foundFormField,L"\x0009",pDispatchContentControlRange)!=S_OK||!foundFormField) {
continue;
}
long fieldType=-1;
_com_dispatch_raw_propget(pDispatchContentControl,wdDISPID_CONTENTCONTROL_TYPE,VT_I4,&fieldType);
BOOL fieldChecked=false;
_com_dispatch_raw_propget(pDispatchContentControl,wdDISPID_CONTENTCONTROL_CHECKED,VT_BOOL,&fieldChecked);
BSTR fieldTitle=NULL;
_com_dispatch_raw_propget(pDispatchContentControl,wdDISPID_CONTENTCONTROL_TITLE,VT_BSTR,&fieldTitle);
XMLStream<<L"<control wdContentControlType=\""<<fieldType<<L"\" wdContentControlChecked=\""<<fieldChecked<<L"\" wdContentControlTitle=\""<<(fieldTitle?fieldTitle:L"")<<L"\">";
if(fieldTitle) SysFreeString(fieldTitle);
_com_dispatch_raw_propget(pDispatchContentControlRange,wdDISPID_RANGE_END,VT_I4,&chunkEnd);
_com_dispatch_raw_propput(pDispatchRange,wdDISPID_RANGE_END,VT_I4,chunkEnd);
break;
}
return foundFormField;
}

Expand Down
53 changes: 43 additions & 10 deletions source/NVDAObjects/window/winword.py
Expand Up @@ -85,6 +85,15 @@
wdFieldFormTextInput=70
wdFieldFormCheckBox=71
wdFieldFormDropDown=83
wdContentControlRichText=0
wdContentControlText=1
wdContentControlPicture=2
wdContentControlComboBox=3
wdContentControlDropdownList=4
wdContentControlBuildingBlockGallery=5
wdContentControlDate=6
wdContentControlGroup=7
wdContentControlCheckBox=8

storyTypeLocalizedLabels={
wdCommentsStory:_("Comments"),
Expand All @@ -105,6 +114,17 @@
wdFieldFormDropDown:controlTypes.ROLE_COMBOBOX,
}

wdContentControlTypesToNVDARoles={
wdContentControlRichText:controlTypes.ROLE_EDITABLETEXT,
wdContentControlText:controlTypes.ROLE_EDITABLETEXT,
wdContentControlPicture:controlTypes.ROLE_GRAPHIC,
wdContentControlComboBox:controlTypes.ROLE_COMBOBOX,
wdContentControlDropdownList:controlTypes.ROLE_COMBOBOX,
wdContentControlDate:controlTypes.ROLE_EDITABLETEXT,
wdContentControlGroup:controlTypes.ROLE_GROUPING,
wdContentControlCheckBox:controlTypes.ROLE_CHECKBOX,
}

winwordWindowIid=GUID('{00020962-0000-0000-C000-000000000046}')

wm_winword_expandToLine=ctypes.windll.user32.RegisterWindowMessageW(u"wm_winword_expandToLine")
Expand Down Expand Up @@ -236,16 +256,29 @@ def _normalizeControlField(self,field):
role=controlTypes.ROLE_EMBEDDEDOBJECT
else:
fieldType=int(field.pop('wdFieldType',-1))
role=wdFieldTypesToNVDARoles.get(fieldType,controlTypes.ROLE_UNKNOWN)
if fieldType==wdFieldFormCheckBox and int(field.get('wdFieldResult','0'))>0:
field['states']=set([controlTypes.STATE_CHECKED])
elif fieldType==wdFieldFormDropDown:
field['value']=field.get('wdFieldResult',None)
fieldStatusText=field.pop('wdFieldStatusText',None)
if fieldStatusText:
field['name']=fieldStatusText
field['alwaysReportName']=True
field['role']=role
if fieldType!=-1:
role=wdFieldTypesToNVDARoles.get(fieldType,controlTypes.ROLE_UNKNOWN)
if fieldType==wdFieldFormCheckBox and int(field.get('wdFieldResult','0'))>0:
field['states']=set([controlTypes.STATE_CHECKED])
elif fieldType==wdFieldFormDropDown:
field['value']=field.get('wdFieldResult',None)
fieldStatusText=field.pop('wdFieldStatusText',None)
if fieldStatusText:
field['name']=fieldStatusText
field['alwaysReportName']=True
else:
fieldType=int(field.get('wdContentControlType',-1))
if fieldType!=-1:
role=wdContentControlTypesToNVDARoles.get(fieldType,controlTypes.ROLE_UNKNOWN)
if role==controlTypes.ROLE_CHECKBOX:
fieldChecked=bool(int(field.get('wdContentControlChecked','0')))
if fieldChecked:
field['states']=set([controlTypes.STATE_CHECKED])
fieldTitle=field.get('wdContentControlTitle',None)
if fieldTitle:
field['name']=fieldTitle
field['alwaysReportName']=True
if role is not None: field['role']=role
storyType=int(field.pop('wdStoryType',0))
if storyType:
name=storyTypeLocalizedLabels.get(storyType,None)
Expand Down

0 comments on commit 0f97a66

Please sign in to comment.