tagging release
[dasher.git] / Src / Win32 / Common / WinMenus.cpp
blob295b423f18fa4ad53666db93e8ad4b8a1fce7a5e
2 #include "WinCommon.h"
3 #include "WinMenus.h"
5 #include "../../Common/Allocators/SimplePooledAlloc.h"
7 #include <comutil.h>
9 // Track memory leaks on Windows to the line that new'd the memory
10 #ifdef _WIN32
11 #ifdef _DEBUG
12 #define DEBUG_NEW new( _NORMAL_BLOCK, THIS_FILE, __LINE__ )
13 #define new DEBUG_NEW
14 #undef THIS_FILE
15 static char THIS_FILE[] = __FILE__;
16 #endif
17 #endif
19 CSimplePooledAlloc < ControlTree > gControlAlloc(20);
21 using namespace WinMenus;
22 std::vector < HWND > windownames;
23 ControlTree *menutree;
24 ControlTree *dummytree;
25 ControlTree *stoptree;
27 ControlTree *WinMenus::GetWindowMenus() {
28 dummytree = gControlAlloc.Alloc();
29 stoptree = gControlAlloc.Alloc();
30 dummytree->pointer = NULL;
31 dummytree->data = 0;
32 dummytree->type = 1;
33 dummytree->next = NULL;
34 dummytree->colour = 8;
35 dummytree->text = "Control";
36 dummytree->children = stoptree;
37 menutree = buildcontroltree();
39 #ifdef ACCESSIBLE
40 EnumDesktopWindows(GetThreadDesktop(GetCurrentThreadId()), WNDENUMPROC(WindowProc), LPARAM(0));
41 return (ProcessWindows());
42 #else
44 return menutree;
46 #endif
50 BOOL CALLBACK WinMenus::WindowProc(HWND hwnd, LPARAM lParam) {
51 windownames.push_back(hwnd);
52 return TRUE;
55 ControlTree *WinMenus::buildcontroltree() {
56 ControlTree *pausetree = gControlAlloc.Alloc();
57 ControlTree *movetree = gControlAlloc.Alloc();
58 ControlTree *deletetree = gControlAlloc.Alloc();
59 ControlTree *speaktree = gControlAlloc.Alloc();
60 stoptree->pointer = (void *)1;
61 stoptree->data = 2;
62 stoptree->children = menutree;
63 stoptree->text = "Stop";
64 stoptree->next = pausetree;
65 stoptree->type = 1;
66 stoptree->colour = 242;
67 stoptree->children = dummytree;
68 pausetree->pointer = (void *)1;
69 pausetree->data = 3;
70 pausetree->children = menutree;
71 pausetree->text = "Pause";
72 pausetree->next = movetree;
73 pausetree->type = 1;
74 pausetree->colour = 241;
75 pausetree->children = dummytree;
76 movetree->pointer = NULL;
77 movetree->data = 0;
78 movetree->children = menutree;
79 movetree->text = "Move";
80 movetree->next = deletetree;
81 movetree->children = buildmovetree(movetree);
82 movetree->type = 1;
83 movetree->colour = -1;
84 deletetree->pointer = NULL;
85 deletetree->data = 0;
86 deletetree->children = builddeletetree(deletetree);
87 deletetree->text = "Delete";
88 deletetree->next = speaktree;
89 deletetree->type = 1;
90 deletetree->colour = -1;
91 speaktree->pointer = 0;
92 speaktree->data = 0;
93 speaktree->children = buildspeaktree(speaktree);
94 speaktree->text = "Speak";
95 speaktree->next = NULL;
96 speaktree->type = 1;
97 speaktree->colour = -1;
98 return stoptree;
101 ControlTree *WinMenus::buildmovetree(ControlTree *movetree) {
102 ControlTree *lefttree = gControlAlloc.Alloc();
103 ControlTree *righttree = gControlAlloc.Alloc();
104 ControlTree *beginningtree = gControlAlloc.Alloc();
105 ControlTree *endtree = gControlAlloc.Alloc();
106 lefttree->pointer = (void *)1;
107 lefttree->data = 11;
108 lefttree->children = lefttree;
109 lefttree->text = "Previous";
110 lefttree->next = righttree;
111 lefttree->type = 1;
112 lefttree->colour = -1;
113 righttree->pointer = (void *)1;
114 righttree->data = 12;
115 righttree->children = lefttree;
116 righttree->text = "Next";
117 righttree->next = beginningtree;
118 righttree->type = 1;
119 righttree->colour = -1;
120 beginningtree->pointer = (void *)1;
121 beginningtree->data = 13;
122 beginningtree->children = lefttree;
123 beginningtree->text = "Beginning";
124 beginningtree->next = endtree;
125 beginningtree->type = 1;
126 beginningtree->colour = -1;
127 endtree->pointer = (void *)1;
128 endtree->data = 14;
129 endtree->children = lefttree;
130 endtree->text = "End";
131 endtree->next = NULL;
132 endtree->type = 1;
133 endtree->colour = -1;
134 return lefttree;
137 ControlTree *WinMenus::builddeletetree(ControlTree *deletetree) {
138 ControlTree *forwardtree = gControlAlloc.Alloc();
139 ControlTree *backwardtree = gControlAlloc.Alloc();
140 ControlTree *forwardchar = gControlAlloc.Alloc();
141 ControlTree *forwardword = gControlAlloc.Alloc();
142 ControlTree *backwardchar = gControlAlloc.Alloc();
143 ControlTree *backwardword = gControlAlloc.Alloc();
145 forwardtree->pointer = NULL;
146 forwardtree->data = 0;
147 forwardtree->next = backwardtree;
148 forwardtree->children = forwardchar;
149 forwardtree->text = "Forward";
150 forwardtree->type = 1;
151 forwardtree->colour = -1;
152 backwardtree->pointer = NULL;
153 backwardtree->data = 0;
154 backwardtree->next = NULL;
155 backwardtree->children = backwardchar;
156 backwardtree->text = "Backward";
157 backwardtree->type = 1;
158 backwardtree->colour = -1;
160 forwardchar->pointer = (void *)1;
161 forwardchar->data = 21;
162 forwardchar->children = forwardtree;
163 forwardchar->next = forwardword;
164 forwardchar->text = "Character";
165 forwardchar->type = 1;
166 forwardchar->colour = -1;
167 forwardword->pointer = (void *)1;
168 forwardword->data = 22;
169 forwardword->children = forwardtree;
170 forwardword->next = NULL;
171 forwardword->text = "Word";
172 forwardword->type = 1;
173 forwardword->colour = -1;
175 backwardchar->pointer = (void *)1;
176 backwardchar->data = 24;
177 backwardchar->children = forwardtree;
178 backwardchar->next = backwardword;
179 backwardchar->text = "Character";
180 backwardchar->type = 1;
181 backwardchar->colour = -1;
182 backwardword->pointer = (void *)1;
183 backwardword->data = 25;
184 backwardword->children = forwardtree;
185 backwardword->next = NULL;
186 backwardword->text = "Word";
187 backwardword->type = 1;
188 backwardword->colour = -1;
190 return forwardtree;
193 ControlTree *WinMenus::buildspeaktree(ControlTree *speaktree) {
194 ControlTree *everythingtree = gControlAlloc.Alloc();
195 ControlTree *newtree = gControlAlloc.Alloc();
196 ControlTree *repeattree = gControlAlloc.Alloc();
198 everythingtree->pointer = (void *)1;
199 everythingtree->data = 4;
200 everythingtree->next = newtree;
201 everythingtree->children = dummytree;
202 everythingtree->text = "Everything";
203 everythingtree->type = 1;
204 everythingtree->colour = -1;
205 newtree->pointer = (void *)1;
206 newtree->data = 5;
207 newtree->next = repeattree;
208 newtree->children = dummytree;
209 newtree->text = "New";
210 newtree->type = 1;
211 newtree->colour = -1;
212 repeattree->pointer = (void *)1;
213 repeattree->data = 6;
214 repeattree->children = dummytree;
215 repeattree->next = NULL;
216 repeattree->text = "Repeat";
217 repeattree->type = 1;
218 repeattree->colour = -1;
220 return everythingtree;
223 #ifdef ACCESSIBLE
225 ControlTree *WinMenus::ProcessWindows() {
226 IAccessible *AccessibleObject = 0;
227 VARIANT AccessibleChild;
228 VariantInit(&AccessibleChild);
229 std::vector < IAccessible * >AccessibleWindows;
230 ControlTree *RootNode;
231 RootNode = gControlAlloc.Alloc();
232 RootNode->parent = NULL;
233 RootNode->children = NULL;
234 RootNode->next = NULL;
235 RootNode->pointer = NULL;
236 RootNode->data = 0;
237 RootNode->type = 0;
238 RootNode->text = "Menus";
239 RootNode->colour = -1;
241 for(int i = 0; i < windownames.size(); i++) {
242 AccessibleObjectFromWindow(windownames[i], OBJID_WINDOW, IID_IAccessible, (void **)&AccessibleObject);
243 if(AccessibleObject != 0) {
244 AddObjectToTree(AccessibleObject, RootNode);
247 return RootNode;
250 bool WinMenus::AddObjectToTree(IAccessible *AccessibleObject, ControlTree *TreeParent) {
251 bool useful = false;
252 VARIANT AccessibleObjectVariant;
253 long NumChildren;
254 ULONG NumFetched;
255 _bstr_t bstrstring;
257 VariantInit(&AccessibleObjectVariant);
258 AccessibleObjectVariant.vt = VT_I4;
259 AccessibleObjectVariant.lVal = CHILDID_SELF;
261 BSTR ObjectName = NULL;
262 HRESULT hr;
263 hr = AccessibleObject->get_accName(AccessibleObjectVariant, &ObjectName);
264 if(hr == S_OK && ObjectName != NULL) {
265 bstrstring = ObjectName;
267 else { // Nameless things are uninteresting
268 return false;
271 // Check if we have any children
273 ControlTree *NewNode = gControlAlloc.Alloc();
274 NewNode->parent = TreeParent;
275 NewNode->children = NULL;
276 NewNode->next = NULL;
277 NewNode->pointer = NULL;
278 NewNode->type = 0;
279 NewNode->colour = -1;
281 // We don't need to hook it into the tree yet
283 // Check how many children we have
285 AccessibleObject->get_accChildCount(&NumChildren);
287 if(NumChildren > 0) { // if we have kids, recurse through them
289 IEnumVARIANT *ParentEnum = NULL;
290 AccessibleObject->QueryInterface(IID_IEnumVARIANT, (PVOID *) & ParentEnum);
292 if(ParentEnum) {
293 ParentEnum->Reset();
296 for(int i = 1; i <= NumChildren; i++) {
298 IDispatch *ChildDispatch = NULL;
299 IAccessible *ChildAccessible = NULL;
301 if(ParentEnum) {
302 ParentEnum->Next(1, &AccessibleObjectVariant, &NumFetched);
304 else {
305 AccessibleObjectVariant.vt = VT_I4;
306 AccessibleObjectVariant.lVal = i;
309 if(AccessibleObjectVariant.vt == VT_I4) {
310 HRESULT hr = AccessibleObject->get_accChild(AccessibleObjectVariant, &ChildDispatch);
312 else {
313 ChildDispatch = AccessibleObjectVariant.pdispVal;
316 if(ChildDispatch != NULL && int (ChildDispatch) != 0xcccccccc) {
317 ChildDispatch->QueryInterface(IID_IAccessible, (void **)&ChildAccessible);
318 ChildDispatch->Release();
321 if(ChildAccessible != NULL) {
322 if(useful == false) {
323 useful = AddObjectToTree(ChildAccessible, NewNode);
325 else {
326 AddObjectToTree(ChildAccessible, NewNode);
331 else {
333 // We have no kids - check whether we're a menu item
334 VARIANT ObjectRole;
335 VariantInit(&ObjectRole);
336 ObjectRole.vt = VT_I4;
337 AccessibleObject->get_accRole(AccessibleObjectVariant, &ObjectRole);
338 if((ObjectRole.iVal == ROLE_SYSTEM_MENUITEM || ObjectRole.iVal == ROLE_SYSTEM_PUSHBUTTON) && NumChildren == 0) {
339 NewNode->pointer = AccessibleObject;
340 NewNode->data = CHILDID_SELF;
341 useful = true;
345 // If no useful children, remove our node
347 if(useful == false) {
348 delete NewNode;
350 else { // If we're useful, add our node to the parent
351 if(TreeParent->children == NULL) {
352 TreeParent->children = NewNode;
354 else {
355 ControlTree *ParentNext;
356 ParentNext = TreeParent->children;
357 while(ParentNext->next != NULL) {
358 ParentNext = ParentNext->next;
360 ParentNext->next = NewNode;
363 // And give it a name
364 NewNode->text = bstrstring;
368 VariantClear(&AccessibleObjectVariant);
370 return useful;
373 #endif