]> git.lyx.org Git - lyx.git/blob - src/frontends/ButtonPolicies.C
cleanup FormDocument read-only handling; UNDO_ALL now working for all policies; tabbe...
[lyx.git] / src / frontends / ButtonPolicies.C
1 // -*- C++ -*-
2 /* ButtonPolicies.C
3  * Provides a state machine implementation of the various button policies
4  * used by the dialogs.
5  * Author: Allan Rae <rae@lyx.org>
6  * This file is part of
7  * ======================================================
8  *
9  *           LyX, The Document Processor
10  *
11  *           Copyright 1995 Matthias Ettrich
12  *           Copyright 1995-2000 The LyX Team.
13  *
14  *           This file Copyright 2000
15  *           Allan Rae
16  * ======================================================
17  */
18
19 #include <config.h>
20 #include "ButtonPolicies.h"
21 #include "debug.h"
22
23
24 // Helper function
25 inline void nextState(ButtonPolicy::State & state,
26                ButtonPolicy::SMInput in,
27                ButtonPolicy::StateMachine s_m,
28                char const * function_name = "nextState")
29 {
30         ButtonPolicy::State tmp = s_m[state][in];
31         if (ButtonPolicy::BOGUS != tmp) {
32                 state = tmp;
33         } else {
34                 lyxerr << function_name
35                        << ": No transition for input "
36                        << in
37                        << " from state "
38                        << state
39                        << std::endl;
40         }
41 }
42
43
44 /*-----------------------------PreferencesPolicy-----------------------------*/
45
46
47 PreferencesPolicy::PreferencesPolicy()
48         : state_(INITIAL),
49           outputs_(APPLIED+1,
50                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
51           state_machine_(APPLIED+1,
52                          StateArray(SMI_TOTAL,
53                                     static_cast<State const &>(BOGUS)))
54 {
55         // Build the state output map
56         outputs_[INITIAL] = CLOSE;
57         outputs_[VALID] = UNDO_ALL | OKAY | APPLY | CANCEL;
58         outputs_[INVALID] = UNDO_ALL | CANCEL;
59         outputs_[APPLIED] = OKAY | CLOSE;
60
61         // Build the state machine one state at a time
62         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
63         //        left out of the state machine and handled explicitly
64         //        in input().  This won't necessarily be true for all
65         //        policies though so I'll leave those two as distinct
66         //        inputs rather than merge them.  For example, a dialog
67         //        that doesn't update it's input fields when reshown
68         //        after being hidden needs a policy where CANCEL and
69         //        HIDE are treated differently.
70         //
71         // State::INITIAL
72         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
73         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
74         state_machine_[INITIAL][SMI_VALID] = VALID;
75         state_machine_[INITIAL][SMI_INVALID] = INVALID;
76         // State::VALID
77         state_machine_[VALID][SMI_VALID] = VALID;
78         state_machine_[VALID][SMI_READ_ONLY] = VALID;
79         state_machine_[VALID][SMI_READ_WRITE] = VALID;
80         state_machine_[VALID][SMI_INVALID] = INVALID;
81         state_machine_[VALID][SMI_APPLY] = APPLIED;
82         state_machine_[VALID][SMI_OKAY] = INITIAL;
83         state_machine_[VALID][SMI_UNDO_ALL] = INITIAL;
84         // State::INVALID
85         state_machine_[INVALID][SMI_VALID] = VALID;
86         state_machine_[INVALID][SMI_INVALID] = INVALID;
87         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
88         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
89         state_machine_[INVALID][SMI_UNDO_ALL] = INITIAL;
90         // State::APPLIED
91         state_machine_[APPLIED][SMI_VALID] = VALID;
92         state_machine_[APPLIED][SMI_INVALID] = INVALID;
93         state_machine_[APPLIED][SMI_OKAY] = INITIAL;
94         state_machine_[APPLIED][SMI_READ_ONLY] = APPLIED;
95         state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
96 }
97
98
99 void PreferencesPolicy::input(SMInput input)
100 {
101         // CANCEL and HIDE always take us to INITIAL for all cases.
102         // Note that I didn't put that special case in the helper function
103         // because it doesn't belong there.  Some other 
104         // This is probably optimising for the wrong case since it occurs as the
105         // dialog will be hidden.  It would have saved a little memory in the
106         // state machine if I could have gotten map working. ARRae 20000813
107         if (SMI_CANCEL == input
108             || SMI_HIDE == input) {
109                 state_ = INITIAL;
110         } else {
111                 nextState(state_,
112                           input,
113                           state_machine_,
114                           "PreferencesPolicy");
115         }
116 }
117
118
119 /*-------------------------------OkCancelPolicy------------------------------*/
120
121
122 OkCancelPolicy::OkCancelPolicy()
123         : state_(INITIAL),
124           outputs_(INVALID+1,
125                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
126           state_machine_(INVALID+1,
127                          StateArray(SMI_TOTAL,
128                                     static_cast<State const &>(BOGUS)))
129 {
130         // Build the state output map
131         outputs_[INITIAL] = CLOSE;
132         outputs_[VALID] = UNDO_ALL | OKAY | CANCEL;
133         outputs_[INVALID] = UNDO_ALL | CANCEL;
134
135         // Build the state machine one state at a time
136         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
137         //        left out of the state machine and handled explicitly
138         //        in input()
139         //
140         // State::INITIAL
141         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
142         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
143         state_machine_[INITIAL][SMI_VALID] = VALID;
144         state_machine_[INITIAL][SMI_INVALID] = INVALID;
145         // State::VALID
146         state_machine_[VALID][SMI_VALID] = VALID;
147         state_machine_[VALID][SMI_READ_ONLY] = VALID;
148         state_machine_[VALID][SMI_READ_WRITE] = VALID;
149         state_machine_[VALID][SMI_INVALID] = INVALID;
150         state_machine_[VALID][SMI_OKAY] = INITIAL;
151         state_machine_[VALID][SMI_UNDO_ALL] = INITIAL;
152         // State::INVALID
153         state_machine_[INVALID][SMI_VALID] = VALID;
154         state_machine_[INVALID][SMI_INVALID] = INVALID;
155         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
156         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
157         state_machine_[INVALID][SMI_UNDO_ALL] = INITIAL;
158 }
159
160
161
162 void OkCancelPolicy::input(SMInput input)
163 {
164         // CANCEL and HIDE always take us to INITIAL for all cases
165         if (SMI_CANCEL == input
166             || SMI_HIDE == input) {
167                 state_ = INITIAL;
168         } else {
169                 nextState(state_, input, state_machine_, "OkCancelPolicy");
170         }
171 }
172
173
174 /*---------------------------OkCancelReadOnlyPolicy-------------------------*/
175
176
177 OkCancelReadOnlyPolicy::OkCancelReadOnlyPolicy()
178         : state_(INITIAL),
179           outputs_(RO_INVALID+1,
180                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
181           state_machine_(RO_INVALID+1,
182                          StateArray(SMI_TOTAL,
183                                     static_cast<State const &>(BOGUS)))
184 {
185         // Build the state output map
186         outputs_[INITIAL] = CLOSE;
187         outputs_[VALID] = UNDO_ALL | OKAY | CANCEL;
188         outputs_[INVALID] = UNDO_ALL | CANCEL;
189         outputs_[RO_INITIAL] = CLOSE;
190         outputs_[RO_VALID] = UNDO_ALL | CANCEL;
191         outputs_[RO_INVALID] = UNDO_ALL | CANCEL;
192
193         // Build the state machine one state at a time
194         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
195         //        left out of the state machine and handled explicitly
196         //        in input()
197         //
198         // State::INITIAL
199         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
200         state_machine_[INITIAL][SMI_VALID] = VALID;
201         state_machine_[INITIAL][SMI_INVALID] = INVALID;
202         state_machine_[INITIAL][SMI_READ_ONLY] = RO_INITIAL;
203         // State::VALID
204         state_machine_[VALID][SMI_VALID] = VALID;
205         state_machine_[VALID][SMI_READ_WRITE] = VALID;
206         state_machine_[VALID][SMI_INVALID] = INVALID;
207         state_machine_[VALID][SMI_OKAY] = INITIAL;
208         state_machine_[VALID][SMI_UNDO_ALL] = INITIAL;
209         state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
210         // State::INVALID
211         state_machine_[INVALID][SMI_INVALID] = INVALID;
212         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
213         state_machine_[INVALID][SMI_VALID] = VALID;
214         state_machine_[INVALID][SMI_UNDO_ALL] = INITIAL;
215         state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
216         // State::RO_INITIAL
217         state_machine_[RO_INITIAL][SMI_READ_ONLY] = RO_INITIAL;
218         state_machine_[RO_INITIAL][SMI_VALID] = RO_VALID;
219         state_machine_[RO_INITIAL][SMI_INVALID] = RO_INVALID;
220         state_machine_[RO_INITIAL][SMI_READ_WRITE] = INITIAL;
221         // State::RO_VALID
222         state_machine_[RO_VALID][SMI_VALID] = RO_VALID;
223         state_machine_[RO_VALID][SMI_READ_ONLY] = RO_VALID;
224         state_machine_[RO_VALID][SMI_INVALID] = RO_INVALID;
225         state_machine_[RO_VALID][SMI_READ_WRITE] = VALID;
226         state_machine_[RO_VALID][SMI_UNDO_ALL] = RO_INITIAL;
227         // State::RO_INVALID
228         state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
229         state_machine_[RO_INVALID][SMI_INVALID] = RO_INVALID;
230         state_machine_[RO_INVALID][SMI_VALID] = RO_VALID;
231         state_machine_[RO_INVALID][SMI_READ_WRITE] = INVALID;
232         state_machine_[RO_INVALID][SMI_UNDO_ALL] = RO_INITIAL;
233 }
234
235
236 void OkCancelReadOnlyPolicy::input(SMInput input)
237 {
238         // CANCEL and HIDE always take us to INITIAL for all cases
239         if (SMI_CANCEL == input
240             || SMI_HIDE == input) {
241                 state_ = INITIAL;
242         } else {
243                 nextState(state_,
244                           input,
245                           state_machine_,
246                           "OkCancelReadOnlyPolicy");
247         }
248 }
249
250
251 /*--------------------------NoRepeatedApplyReadOnlyPolicy----------------------*/
252
253
254 NoRepeatedApplyReadOnlyPolicy::NoRepeatedApplyReadOnlyPolicy()
255         : state_(INITIAL),
256           outputs_(RO_INVALID+1,
257                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
258           state_machine_(RO_INVALID+1,
259                          StateArray(SMI_TOTAL,
260                                     static_cast<State const &>(BOGUS)))
261 {
262         // Build the state output map
263         outputs_[INITIAL] = CLOSE;
264         outputs_[VALID] = UNDO_ALL | OKAY | APPLY | CANCEL;
265         outputs_[INVALID] = UNDO_ALL | CANCEL;
266         outputs_[RO_INITIAL] = CLOSE;
267         outputs_[RO_VALID] = UNDO_ALL | CANCEL;
268         outputs_[RO_INVALID] = UNDO_ALL | CANCEL;
269
270         // Build the state machine one state at a time
271         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
272         //        left out of the state machine and handled explicitly
273         //        in input()
274         //
275         // State::INITIAL
276         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
277         state_machine_[INITIAL][SMI_VALID] = VALID;
278         state_machine_[INITIAL][SMI_INVALID] = INVALID;
279         state_machine_[INITIAL][SMI_READ_ONLY] = RO_INITIAL;
280         // State::VALID
281         state_machine_[VALID][SMI_VALID] = VALID;
282         state_machine_[VALID][SMI_READ_WRITE] = VALID;
283         state_machine_[VALID][SMI_INVALID] = INVALID;
284         state_machine_[VALID][SMI_OKAY] = INITIAL;
285         state_machine_[VALID][SMI_APPLY] = INITIAL;
286         state_machine_[VALID][SMI_UNDO_ALL] = INITIAL;
287         state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
288         // State::INVALID
289         state_machine_[INVALID][SMI_INVALID] = INVALID;
290         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
291         state_machine_[INVALID][SMI_VALID] = VALID;
292         state_machine_[INVALID][SMI_UNDO_ALL] = INITIAL;
293         state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
294         // State::RO_INITIAL
295         state_machine_[RO_INITIAL][SMI_READ_ONLY] = RO_INITIAL;
296         state_machine_[RO_INITIAL][SMI_VALID] = RO_VALID;
297         state_machine_[RO_INITIAL][SMI_INVALID] = RO_INVALID;
298         state_machine_[RO_INITIAL][SMI_READ_WRITE] = INITIAL;
299         // State::RO_VALID
300         state_machine_[RO_VALID][SMI_VALID] = RO_VALID;
301         state_machine_[RO_VALID][SMI_READ_ONLY] = RO_VALID;
302         state_machine_[RO_VALID][SMI_INVALID] = RO_INVALID;
303         state_machine_[RO_VALID][SMI_READ_WRITE] = VALID;
304         state_machine_[RO_VALID][SMI_UNDO_ALL] = RO_INITIAL;
305         // State::RO_INVALID
306         state_machine_[RO_INVALID][SMI_INVALID] = RO_INVALID;
307         state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
308         state_machine_[RO_INVALID][SMI_VALID] = RO_VALID;
309         state_machine_[RO_INVALID][SMI_READ_WRITE] = INVALID;
310         state_machine_[RO_INVALID][SMI_UNDO_ALL] = RO_INITIAL;
311 }
312
313
314 void NoRepeatedApplyReadOnlyPolicy::input(SMInput input)
315 {
316         // CANCEL and HIDE always take us to INITIAL for all cases
317         if (SMI_CANCEL == input
318             || SMI_HIDE == input) {
319                 state_ = INITIAL;
320         } else {
321                 nextState(state_,
322                           input,
323                           state_machine_,
324                           "NoRepeatedApplyReadOnlyPolicy");
325         }
326 }
327
328
329 /*--------------------------OkApplyCancelReadOnlyPolicy----------------------*/
330
331
332 OkApplyCancelReadOnlyPolicy::OkApplyCancelReadOnlyPolicy()
333         : state_(INITIAL),
334           outputs_(RO_APPLIED+1,
335                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
336           state_machine_(RO_APPLIED+1,
337                          StateArray(SMI_TOTAL,
338                                     static_cast<State const &>(BOGUS)))
339 {
340         // Build the state output map
341         outputs_[INITIAL] = CLOSE;
342         outputs_[VALID] = UNDO_ALL | OKAY | APPLY | CANCEL;
343         outputs_[INVALID] = UNDO_ALL | CANCEL;
344         outputs_[APPLIED] = OKAY | APPLY | CLOSE;
345         outputs_[RO_INITIAL] = CLOSE;
346         outputs_[RO_VALID] = UNDO_ALL | CANCEL;
347         outputs_[RO_INVALID] = UNDO_ALL | CANCEL;
348         outputs_[RO_APPLIED] = CLOSE;
349
350         // Build the state machine one state at a time
351         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
352         //        left out of the state machine and handled explicitly
353         //        in input()
354         //
355         // State::INITIAL
356         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
357         state_machine_[INITIAL][SMI_VALID] = VALID;
358         state_machine_[INITIAL][SMI_INVALID] = INVALID;
359         state_machine_[INITIAL][SMI_READ_ONLY] = RO_INITIAL;
360         // State::VALID
361         state_machine_[VALID][SMI_VALID] = VALID;
362         state_machine_[VALID][SMI_READ_WRITE] = VALID;
363         state_machine_[VALID][SMI_INVALID] = INVALID;
364         state_machine_[VALID][SMI_OKAY] = INITIAL;
365         state_machine_[VALID][SMI_UNDO_ALL] = INITIAL;
366         state_machine_[VALID][SMI_APPLY] = APPLIED;
367         state_machine_[VALID][SMI_READ_ONLY] = RO_VALID;
368         // State::INVALID
369         state_machine_[INVALID][SMI_INVALID] = INVALID;
370         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
371         state_machine_[INVALID][SMI_VALID] = VALID;
372         state_machine_[INVALID][SMI_UNDO_ALL] = INITIAL;
373         state_machine_[INVALID][SMI_READ_ONLY] = RO_INVALID;
374         // State::APPLIED
375         state_machine_[APPLIED][SMI_APPLY] = APPLIED;
376         state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
377         state_machine_[APPLIED][SMI_VALID] = VALID;
378         state_machine_[APPLIED][SMI_INVALID] = INVALID;
379         state_machine_[APPLIED][SMI_OKAY] = INITIAL;
380         state_machine_[APPLIED][SMI_READ_ONLY] = RO_APPLIED;
381         // State::RO_INITIAL
382         state_machine_[RO_INITIAL][SMI_READ_ONLY] = RO_INITIAL;
383         state_machine_[RO_INITIAL][SMI_VALID] = RO_VALID;
384         state_machine_[RO_INITIAL][SMI_INVALID] = RO_INVALID;
385         state_machine_[RO_INITIAL][SMI_READ_WRITE] = INITIAL;
386         // State::RO_VALID
387         state_machine_[RO_VALID][SMI_VALID] = RO_VALID;
388         state_machine_[RO_VALID][SMI_READ_ONLY] = RO_VALID;
389         state_machine_[RO_VALID][SMI_INVALID] = RO_INVALID;
390         state_machine_[RO_VALID][SMI_READ_WRITE] = VALID;
391         state_machine_[RO_VALID][SMI_UNDO_ALL] = RO_INITIAL;
392         // State::RO_INVALID
393         state_machine_[RO_INVALID][SMI_INVALID] = RO_INVALID;
394         state_machine_[RO_INVALID][SMI_READ_ONLY] = RO_INVALID;
395         state_machine_[RO_INVALID][SMI_VALID] = RO_VALID;
396         state_machine_[RO_INVALID][SMI_READ_WRITE] = INVALID;
397         state_machine_[RO_INVALID][SMI_UNDO_ALL] = RO_INITIAL;
398         // State::RO_APPLIED
399         state_machine_[RO_APPLIED][SMI_READ_ONLY] = RO_APPLIED;
400         state_machine_[RO_APPLIED][SMI_INVALID] = RO_INVALID;
401         state_machine_[RO_APPLIED][SMI_VALID] = RO_VALID;
402         state_machine_[RO_APPLIED][SMI_READ_WRITE] = APPLIED;
403 }
404
405
406 void OkApplyCancelReadOnlyPolicy::input(SMInput input)
407 {
408         // CANCEL and HIDE always take us to INITIAL for all cases
409         if (SMI_CANCEL == input
410             || SMI_HIDE == input) {
411                 state_ = INITIAL;
412         } else {
413                 nextState(state_,
414                           input,
415                           state_machine_,
416                           "OkApplyCancelReadOnlyPolicy");
417         }
418 }
419
420
421 /*--------------------------OkApplyCancelPolicy----------------------*/
422
423
424 OkApplyCancelPolicy::OkApplyCancelPolicy()
425         : state_(INITIAL),
426           outputs_(APPLIED+1,
427                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
428           state_machine_(APPLIED+1,
429                          StateArray(SMI_TOTAL,
430                                     static_cast<State const &>(BOGUS)))
431 {
432         // Build the state output map
433         outputs_[INITIAL] = CLOSE;
434         outputs_[VALID] = UNDO_ALL | OKAY | APPLY | CANCEL;
435         outputs_[INVALID] = UNDO_ALL | CANCEL;
436         outputs_[APPLIED] = OKAY | APPLY | CLOSE;
437
438         // Build the state machine one state at a time
439         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
440         //        left out of the state machine and handled explicitly
441         //        in input()
442         //
443         // State::INITIAL
444         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
445         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
446         state_machine_[INITIAL][SMI_VALID] = VALID;
447         state_machine_[INITIAL][SMI_INVALID] = INVALID;
448         // State::VALID
449         state_machine_[VALID][SMI_VALID] = VALID;
450         state_machine_[VALID][SMI_READ_ONLY] = VALID;
451         state_machine_[VALID][SMI_READ_WRITE] = VALID;
452         state_machine_[VALID][SMI_INVALID] = INVALID;
453         state_machine_[VALID][SMI_OKAY] = INITIAL;
454         state_machine_[VALID][SMI_UNDO_ALL] = INITIAL;
455         state_machine_[VALID][SMI_APPLY] = APPLIED;
456         // State::INVALID
457         state_machine_[INVALID][SMI_INVALID] = INVALID;
458         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
459         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
460         state_machine_[INVALID][SMI_VALID] = VALID;
461         state_machine_[INVALID][SMI_UNDO_ALL] = INITIAL;
462         // State::APPLIED
463         state_machine_[APPLIED][SMI_APPLY] = APPLIED;
464         state_machine_[APPLIED][SMI_READ_ONLY] = APPLIED;
465         state_machine_[APPLIED][SMI_READ_WRITE] = APPLIED;
466         state_machine_[APPLIED][SMI_VALID] = VALID;
467         state_machine_[APPLIED][SMI_INVALID] = INVALID;
468         state_machine_[APPLIED][SMI_OKAY] = INITIAL;
469 }
470
471
472 void OkApplyCancelPolicy::input(SMInput input)
473 {
474         // CANCEL and HIDE always take us to INITIAL for all cases
475         if (SMI_CANCEL == input
476             || SMI_HIDE == input) {
477                 state_ = INITIAL;
478         } else {
479                 nextState(state_,
480                           input,
481                           state_machine_,
482                           "OkApplyCancelPolicy");
483         }
484 }
485
486
487 /*--------------------------NoRepeatedApplyPolicy----------------------*/
488
489
490 NoRepeatedApplyPolicy::NoRepeatedApplyPolicy()
491         : state_(INITIAL),
492           outputs_(INVALID+1,
493                    static_cast<int const &>(OKAY | APPLY | CANCEL | UNDO_ALL)),
494           state_machine_(INVALID+1,
495                          StateArray(SMI_TOTAL,
496                                     static_cast<State const &>(BOGUS)))
497 {
498         // Build the state output map
499         outputs_[INITIAL] = CLOSE;
500         outputs_[VALID] = UNDO_ALL | OKAY | APPLY | CANCEL;
501         outputs_[INVALID] = UNDO_ALL | CANCEL;
502
503         // Build the state machine one state at a time
504         // NOTE:  Since CANCEL and HIDE always go to INITIAL they are
505         //        left out of the state machine and handled explicitly
506         //        in input()
507         //
508         // State::INITIAL
509         state_machine_[INITIAL][SMI_READ_ONLY] = INITIAL;
510         state_machine_[INITIAL][SMI_READ_WRITE] = INITIAL;
511         state_machine_[INITIAL][SMI_VALID] = VALID;
512         state_machine_[INITIAL][SMI_INVALID] = INVALID;
513         // State::VALID
514         state_machine_[VALID][SMI_VALID] = VALID;
515         state_machine_[VALID][SMI_READ_ONLY] = VALID;
516         state_machine_[VALID][SMI_READ_WRITE] = VALID;
517         state_machine_[VALID][SMI_INVALID] = INVALID;
518         state_machine_[VALID][SMI_OKAY] = INITIAL;
519         state_machine_[VALID][SMI_APPLY] = INITIAL;
520         state_machine_[VALID][SMI_UNDO_ALL] = INITIAL;
521         // State::INVALID
522         state_machine_[INVALID][SMI_INVALID] = INVALID;
523         state_machine_[INVALID][SMI_READ_ONLY] = INVALID;
524         state_machine_[INVALID][SMI_READ_WRITE] = INVALID;
525         state_machine_[INVALID][SMI_VALID] = VALID;
526         state_machine_[INVALID][SMI_UNDO_ALL] = INITIAL;
527 }
528
529
530 void NoRepeatedApplyPolicy::input(SMInput input)
531 {
532         // CANCEL and HIDE always take us to INITIAL for all cases
533         if (SMI_CANCEL == input
534             || SMI_HIDE == input) {
535                 state_ = INITIAL;
536         } else {
537                 nextState(state_,
538                           input,
539                           state_machine_,
540                           "NoRepeatedApplyPolicy");
541         }
542 }