Package NVDAObjects :: Package window :: Module scintilla
[hide private]
[frames] | no frames]

Source Code for Module NVDAObjects.window.scintilla

  1  import ctypes 
  2  import IAccessibleHandler 
  3  import speech 
  4  import textInfos.offsets 
  5  import winKernel 
  6  import winUser 
  7  import globalVars 
  8  import controlTypes 
  9  import config 
 10  from . import Window 
 11  from .. import NVDAObjectTextInfo 
 12  from ..behaviors import EditableTextWithAutoSelectDetection 
 13  import locale 
 14  import watchdog 
 15   
 16  #Window messages 
 17  SCI_POSITIONFROMPOINT=2022 
 18  SCI_POINTXFROMPOSITION=2164 
 19  SCI_POINTYFROMPOSITION=2165 
 20  SCI_GETTEXTRANGE=2162 
 21  SCI_GETTEXT=2182 
 22  SCI_GETTEXTLENGTH=2183 
 23  SCI_GETLENGTH=2006 
 24  SCI_GETCURRENTPOS=2008 
 25  SCI_GETANCHOR=2009 
 26  SCI_GOTOPOS=2025 
 27  SCI_SETCURRENTPOS=2141 
 28  SCI_GETSELECTIONSTART=2143 
 29  SCI_GETSELECTIONEND=2145 
 30  SCI_SETSEL=2160 
 31  SCI_GETLINEENDPOSITION=2136 
 32  SCI_GETLINECOUNT=2154 
 33  SCI_LINEFROMPOSITION=2166 
 34  SCI_POSITIONFROMLINE=2167 
 35  SCI_LINELENGTH=2350 
 36  SCI_GETSTYLEAT=2010 
 37  SCI_STYLEGETFONT=2486 
 38  SCI_STYLEGETSIZE=2485 
 39  SCI_STYLEGETBOLD=2483 
 40  SCI_STYLEGETITALIC=2484 
 41  SCI_STYLEGETUNDERLINE=2488 
 42  SCI_WORDSTARTPOSITION=2266 
 43  SCI_WORDENDPOSITION=2267 
 44  SCI_GETCODEPAGE=2137 
 45  SCI_POSITIONAFTER=2418 
 46   
 47  #constants 
 48  STYLE_DEFAULT=32 
 49  SC_CP_UTF8=65001 
 50   
51 -class CharacterRangeStruct(ctypes.Structure):
52 _fields_=[ 53 ('cpMin',ctypes.c_long), 54 ('cpMax',ctypes.c_long), 55 ]
56
57 -class TextRangeStruct(ctypes.Structure):
58 _fields_=[ 59 ('chrg',CharacterRangeStruct), 60 ('lpstrText',ctypes.c_char_p), 61 ]
62
63 -class ScintillaTextInfo(textInfos.offsets.OffsetsTextInfo):
64
65 - def _getOffsetFromPoint(self,x,y):
66 return watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_POSITIONFROMPOINT,x,y)
67
68 - def _getPointFromOffset(self,offset):
69 point=textInfos.Point( 70 watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_POINTXFROMPOSITION,None,offset), 71 watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_POINTYFROMPOSITION,None,offset) 72 ) 73 if point.x and point.y: 74 return point 75 else: 76 raise NotImplementedError
77
78 - def _getFormatFieldAndOffsets(self,offset,formatConfig,calculateOffsets=True):
79 style=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETSTYLEAT,offset,0) 80 if calculateOffsets: 81 #we need to manually see how far the style goes, limit to line 82 lineStart,lineEnd=self._getLineOffsets(offset) 83 startOffset=offset 84 while startOffset>lineStart: 85 curStyle=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETSTYLEAT,startOffset-1,0) 86 if curStyle==style: 87 startOffset-=1 88 else: 89 break 90 endOffset=offset+1 91 while endOffset<lineEnd: 92 curStyle=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETSTYLEAT,endOffset,0) 93 if curStyle==style: 94 endOffset+=1 95 else: 96 break 97 else: 98 startOffset,endOffset=(self._startOffset,self._endOffset) 99 formatField=textInfos.FormatField() 100 if formatConfig["reportFontName"]: 101 #To get font name, We need to allocate memory with in Scintilla's process, and then copy it out 102 fontNameBuf=ctypes.create_string_buffer(32) 103 internalBuf=winKernel.virtualAllocEx(self.obj.processHandle,None,len(fontNameBuf),winKernel.MEM_COMMIT,winKernel.PAGE_READWRITE) 104 try: 105 watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_STYLEGETFONT,style, internalBuf) 106 winKernel.readProcessMemory(self.obj.processHandle,internalBuf,fontNameBuf,len(fontNameBuf),None) 107 finally: 108 winKernel.virtualFreeEx(self.obj.processHandle,internalBuf,0,winKernel.MEM_RELEASE) 109 formatField["font-name"]=fontNameBuf.value 110 if formatConfig["reportFontSize"]: 111 formatField["font-size"]="%spt"%watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_STYLEGETSIZE,style,0) 112 if formatConfig["reportLineNumber"]: 113 formatField["line-number"]=self._getLineNumFromOffset(offset)+1 114 if formatConfig["reportFontAttributes"]: 115 formatField["bold"]=bool(watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_STYLEGETBOLD,style,0)) 116 formatField["italic"]=bool(watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_STYLEGETITALIC,style,0)) 117 formatField["underline"]=bool(watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_STYLEGETUNDERLINE,style,0)) 118 return formatField,(startOffset,endOffset)
119
120 - def _getCaretOffset(self):
121 return watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETCURRENTPOS,0,0)
122
123 - def _setCaretOffset(self,offset):
124 watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GOTOPOS,offset,0)
125
126 - def _getSelectionOffsets(self):
127 start=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETSELECTIONSTART,0,0) 128 end=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETSELECTIONEND,0,0) 129 return (start,end)
130
131 - def _setSelectionOffsets(self,start,end):
132 watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_SETSEL,start,end)
133
134 - def _getStoryText(self):
135 if not hasattr(self,'_storyText'): 136 storyLength=self._getStoryLength() 137 self._storyText=self._getTextRange(0,storyLength) 138 return self._storyText
139
140 - def _getStoryLength(self):
141 if not hasattr(self,'_storyLength'): 142 self._storyLength=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETTEXTLENGTH,0,0) 143 return self._storyLength
144
145 - def _getLineCount(self):
146 return watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETLINECOUNT,0,0)
147
148 - def _getTextRange(self,start,end):
149 bufLen=(end-start)+1 150 textRange=TextRangeStruct() 151 textRange.chrg.cpMin=start 152 textRange.chrg.cpMax=end 153 processHandle=self.obj.processHandle 154 internalBuf=winKernel.virtualAllocEx(processHandle,None,bufLen,winKernel.MEM_COMMIT,winKernel.PAGE_READWRITE) 155 try: 156 textRange.lpstrText=internalBuf 157 internalTextRange=winKernel.virtualAllocEx(processHandle,None,ctypes.sizeof(textRange),winKernel.MEM_COMMIT,winKernel.PAGE_READWRITE) 158 try: 159 winKernel.writeProcessMemory(processHandle,internalTextRange,ctypes.byref(textRange),ctypes.sizeof(textRange),None) 160 watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETTEXTRANGE,0,internalTextRange) 161 finally: 162 winKernel.virtualFreeEx(processHandle,internalTextRange,0,winKernel.MEM_RELEASE) 163 buf=ctypes.create_string_buffer(bufLen) 164 winKernel.readProcessMemory(processHandle,internalBuf,buf,bufLen,None) 165 finally: 166 winKernel.virtualFreeEx(processHandle,internalBuf,0,winKernel.MEM_RELEASE) 167 cp=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETCODEPAGE,0,0) 168 if cp==SC_CP_UTF8: 169 return unicode(buf.value, errors="replace", encoding="utf-8") 170 else: 171 return unicode(buf.value, errors="replace", encoding=locale.getlocale()[1])
172
173 - def _getWordOffsets(self,offset):
174 start=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_WORDSTARTPOSITION,offset,0) 175 end=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_WORDENDPOSITION,start,0) 176 if end<=offset: 177 start=end 178 end=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_WORDENDPOSITION,offset,0) 179 return [start,end]
180
181 - def _getLineNumFromOffset(self,offset):
182 return watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_LINEFROMPOSITION,offset,0)
183
184 - def _getLineOffsets(self,offset):
185 line=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_LINEFROMPOSITION,offset,0) 186 start=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_POSITIONFROMLINE,line,0) 187 end=start+watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_LINELENGTH,line,0) 188 return (start,end)
189
190 - def _getParagraphOffsets(self,offset):
191 return self._getLineOffsets(offset)
192
193 - def _getCharacterOffsets(self,offset):
194 return [offset,watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_POSITIONAFTER,offset,0)]
195 196 #The Scintilla NVDA object, inherists the generic MSAA NVDA object
197 -class Scintilla(EditableTextWithAutoSelectDetection, Window):
198 199 TextInfo=ScintillaTextInfo 200 201 #The name of the object is gotten by the standard way of getting a window name, can't use MSAA name (since it contains all the text)
202 - def _get_name(self):
203 return winUser.getWindowText(self.windowHandle)
204 205 #The role of the object should be editable text
206 - def _get_role(self):
208
209 - def _get_states(self):
210 states = super(Scintilla, self)._get_states() 211 # Scintilla controls are always multiline. 212 states.add(controlTypes.STATE_MULTILINE) 213 return states
214