aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/EmEventOutput.h
blob: 6566ffdbed9f82c1fd61934aba623140bdfd7c39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/* -*- mode: C++; tab-width: 4 -*- */
/* ===================================================================== *\
	Copyright (c) 2001 Palm, Inc. or its subsidiaries.
	All rights reserved.

	This file is part of the Palm OS Emulator.

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.
\* ===================================================================== */

#ifndef EmEventOutput_h
#define EmEventOutput_h

#include "EmEventPlayback.h"	// EmRecordedEvent
#include "EmStructs.h"			// StringList

#include <string>				// string
#include <strstream>			// strstream


/*
	EmEventOutput tries to write out a human-readable list of steps from a 
	Gremlin event list.  This process has two parts: gathering information 
	while the gremlin events are being played back, and running through the 
	event list and outputting the steps.

	The information-gathering happens when EmEventPlayback::ReplayGetEvent
	or ReplayGetPen calls EmEventOutput::GetEventInfo, right after a gremlin
	event has been posted. GetEventInfo gets info about the posted event, 
	or about a previous event if necessary. This info is stored in the 
	gremlin event structure for later use.

	The step outputting part currently happens when an event minimization 
	completes, and EmMinimize::MinimizationComplete calles 
	EmEventOutput::OutputEvents.

	This system is accessed from the following locations:

		* EmEventPlayback	: Reports that events are being inserted into the
							  system, and that EmEventOutput may want to gather
							  additional contextual information about the event
							  to be used when later logging the event.  To do
							  this, EmEventPlayback calls GetEventInfo, passing
							  in the event being played back.

		* EmMinimize		: Turns information gather on and off.
							  Triggers final output of events when minimization
							  is completed.

		* SysHeadpatch::FrmPopupForm
							: Report that a form is popping up.


	Output is according to this grammar:
	------------------------------------

	All steps are assumed to be numbered starting at one and incrementing by
	one.

	bugReport ::==
		appStart
		events*
		crash

	appStart ::==
		Start "appName" appVersion on a deviceName running Palm OS osVersion.

	events ::==
		tap | write | startApp |
		ejectCard # NYI

	ranking ::==
		first | second | third | nth | last
		# counted top to bottom, left to right

	formObjectType ::==
		button | trigger | selector | checkbox |
		pushbutton | gadget | field | list | table

	changeForm ::==
		to go to { the "formName" view | a new view }
		to open { the "formName" dialog | a new dialog }
		to popup a dialog |

	tapStart ::==
		Tap the "buttonName" {button | trigger | selector | checkbox} |
		Tap the {ranking} {formObjectType} {from the top} |
		Tap in the {ranking} field {from the top} {after the text "fieldText" | at the beginning} |
		Tap the list item "itemName" |
		Tap the {ranking} list item |
		Tap the {ranking} list {from the top}, in the "itemName" item |
		Tap the {ranking} list {from the top}, in the {ranking} item |
		Tap the {ranking} list {from the top} at x, y |
		Tap in the {ranking} table {from the top} at column n row n |
		Tap in the {ranking} table {from the top} at x, y |
		Tap the scroll {up | down} button | # NYI
		Tap the "menuName \ menuItem"  menu item | # NYI
		Tap in the title | # NYI
		Tap at x, y

	tap ::==
		tapStart {changeForm}.

	key ::==
		<backspace> | 
		<tab> | 
		<new line> |
		<carriage return> |
		<delete> |
		c | # normal characters from 0x20 - 0x7E
		<nnn> | # extended characters from 0x80 - 0xFF

	keyButton ::==
		page up | page down |
		left arrow | right arrow | up arrow | down arrow |
		prev field | next field |
		menu |
		command |
		launch |
		keyboard |
		find |
		calc |
		...

	keyAppEvent ::==
		low battery |
		auto off |
		exgtest |
		send data |
		ir receive |
		...

	write ::==
		Write "key+". | # combine adjacent keystrokes if possible.
		Tap the keyButton button. |
		Application receives a keyAppEvent event. |
		Write character nnn. # for key events with no other description

	startApp ::==
		Switch to "appName appVersion" from "oldAppName oldAppVersion". | 
		Switch to any other app. | # if the crash happens before the app exits
		Relaunch "appName appVersion".

	crash ::==
		Crash with error "errorDescription".
		stackCrawl
*/

// As events are replayed, we are called to gather contextual information
// about that event.  We use that contextual information when preparing
// out English output.  The event being replayed is stored along with bits
// and pieces of contextual information in the following structure.

struct EmEventInfo
{
	EmRecordedEvent			event;

	string					newFormText;
	StringList				stackCrawl;
	string					text;
	FormObjectKind			objKind;
	UInt16					objID;
	Int16					rank;
	Int16					row;
	Int16					column;
	ControlStyleType		style;

	// Silkscreen button info
	WChar					asciiCode;
	UInt16					keyCode;
	UInt16					modifiers;
};

typedef vector<EmEventInfo>	EmEventInfoList;

class EmEventOutput
{
	// Interface for gathering event info:

	public:
		static void				StartGatheringInfo		(void);
		static Bool				IsGatheringInfo			(void);
		static void				GatherInfo				(Bool);

		// Called by EmEventPlayback when returning a new event to be played back.

		static void				GetEventInfo			(const EmRecordedEvent&);

		// Called by SysHeadpatch::FrmPopupForm to report that a new form is
		// being popped up.

		static void				PoppingUpForm			(void);

		// Called by Errors::HandleDialog to report that an error occurred
		// and report the text.

		static void				ErrorOccurred			(const string&);

	private:
		static void				GetAwaitedEventInfo		(void);
		static void				GetPenEventInfo			(EmEventInfo&);
		static void				GetAppSwitchEventInfo	(EmEventInfo&);

	// Interface for outputting:

	public:
		// Called by Minimization when minimization is done and the accumulated
		// information needs to be written out.

		static void				OutputEvents			(strstream&);

		// Utility routine to list a stack crawl.  Exported here so that we
		// can share it with EmMinimize, which uses it when reporting that
		// it failed to produce an error on the last run.

		static void				OutputStack				(strstream&, const StringList&);

	private:
		static void				OutputStartStep			(strstream&);
		static void				OutputKeyEventStep		(EmEventInfoList::iterator&, strstream&);
		static void				OutputPenEventStep		(const EmEventInfo&, strstream&);
		static void				OutputAppSwitchEventStep(const EmEventInfo&, strstream&);
		static void				OutputErrorEvent		(const EmEventInfo&, strstream&);

	// Globals:

	private:
		static EmEventInfoList	fgEventInfo;
		static Bool				fgIsGatheringInfo;
		static int				fgCounter;
		static UInt16			fgPreviousFormID;
		static Bool				fgEventAwaitingInfo;
		static Bool				fgWaitForPenUp;
		static StringList		fgLastStackCrawl;
};

#endif // EmEventOutput_h