1/*
2	Copyright 2005, Francois Revol.   All Rights Reserved.
3	This file may be used under the terms of the Be Sample Code License.
4*/
5
6#include <stdlib.h>
7#include <string.h>
8#include <ctype.h>
9
10#include <Debug.h>
11#include <List.h>
12#include <Message.h>
13#include <OS.h>
14
15#include <Application.h>
16#include <Alert.h>
17#include <Menu.h>
18#include <MenuItem.h>
19#include <Handler.h>
20#include <Locker.h>
21#include <Autolock.h>
22
23
24#include <add-ons/input_server/InputServerMethod.h>
25
26#ifndef _T
27#define _T(s) s
28#endif
29
30#include "T9Icon.h"
31
32extern "C" _EXPORT BInputServerMethod* instantiate_input_method();
33
34enum T9Mode {
35  WordMode,
36  CharMode,
37  NumMode
38};
39
40
41// modes: =Abc / Abc / 123
42// flags:  Abc / ABC / abc
43
44class T9InputServerMethod : public BInputServerMethod, public BHandler
45{
46public:
47  T9InputServerMethod();
48  virtual ~T9InputServerMethod();
49  virtual filter_result Filter(BMessage *message, BList *outList);
50  virtual status_t MethodActivated(bool active);
51  virtual void MessageReceived(BMessage *message);
52
53  bool IsEnabled() const { return fEnabled; };
54  T9Mode Mode() const { return fMode; };
55  void SetMode(T9Mode mode);
56private:
57  bool fEnabled;
58  T9Mode fMode;
59  BMenu *fDeskbarMenu;
60  BLocker fLocker;
61  BString fTyped; /* what has been typed so far for the current word */
62};
63
64
65
66
67BInputServerMethod* instantiate_input_method()
68{
69	PRINT(("%s\n", __FUNCTION__));
70	return (new T9InputServerMethod());
71}
72
73
74T9InputServerMethod::T9InputServerMethod()
75  : BInputServerMethod("T9", T9IconData),
76    BHandler("T9IMHandler"),
77    fEnabled(false),
78    fMode(WordMode),
79    fDeskbarMenu(NULL),
80    fLocker("T9IM")
81{
82	PRINT(("%s\n", __FUNCTION__));
83
84	if (be_app) {
85	  be_app->Lock();
86	  be_app->AddHandler(this);
87	  be_app->Unlock();
88	}
89
90	//
91	fDeskbarMenu = new BMenu(_T("Mode"));
92
93
94	BMessage *msg = new BMessage('SetM');
95	msg->AddInt32("t9mode", WordMode);
96	BMenuItem *item;
97	item = new BMenuItem(_T("Word mode"), msg);
98	item->SetMarked(true);
99	fDeskbarMenu->AddItem(item);
100	msg = new BMessage('SetM');
101	msg->AddInt32("t9mode", CharMode);
102	item = new BMenuItem(_T("Character mode"), msg);
103	fDeskbarMenu->AddItem(item);
104	msg = new BMessage('SetM');
105	msg->AddInt32("t9mode", NumMode);
106	item = new BMenuItem(_T("Numeric mode"), msg);
107	fDeskbarMenu->AddItem(item);
108	fDeskbarMenu->SetFont(be_plain_font);
109	// doesn't seem to work here
110	//fDeskbarMenu->SetRadioMode(true);
111	//fDeskbarMenu->SetLabelFromMarked(true);
112
113	SetMenu(fDeskbarMenu, BMessenger(this));
114}
115
116T9InputServerMethod::~T9InputServerMethod()
117{
118	PRINT(("%s\n", __FUNCTION__));
119	SetMenu(NULL, BMessenger());
120	delete fDeskbarMenu;
121	if (be_app) {
122	  be_app->Lock();
123	  be_app->RemoveHandler(this);
124	  be_app->Unlock();
125	}
126}
127
128filter_result T9InputServerMethod::Filter(BMessage *message, BList *outList)
129{
130	status_t err;
131	filter_result res = B_DISPATCH_MESSAGE;
132	bool keyUp = false;
133	BString bytes;
134
135	if (!IsEnabled())
136		return B_DISPATCH_MESSAGE;
137
138	switch (message->what) {
139	case B_KEY_UP:
140	  keyUp = true;
141	case B_KEY_DOWN:
142	  if (message->FindString("bytes", &bytes) < B_OK)
143	    break;
144	  if (bytes.Length() == 1) {
145	    BAutolock l(fLocker);
146
147	    if (fMode == NumMode)
148	      break;
149	  }
150	  break;
151	default:
152	  break;
153	}
154
155	return (res);
156}
157
158status_t T9InputServerMethod::MethodActivated(bool active)
159{
160  fEnabled = active;
161  return BInputServerMethod::MethodActivated(active);
162}
163
164void T9InputServerMethod::MessageReceived(BMessage *message)
165{
166  int32 v;
167  switch (message->what) {
168  case 'SetM':
169    if (message->FindInt32("t9mode", &v) < B_OK)
170      break;
171    SetMode((T9Mode)v);
172
173    /*{
174      BString s;
175      s << v;
176      s << " - ";
177      s << (long) fDeskbarMenu->FindMarked();
178      s << " - ";
179      s << (long) fDeskbarMenu->ItemAt(v);
180      BAlert *a = new BAlert("Plop", s.String(), "OK");
181      a->SetFlags(a->Flags() | B_CLOSE_ON_ESCAPE);
182      a->Go(NULL);
183      }*/
184    break;
185  default:
186    BHandler::MessageReceived(message);
187    break;
188  }
189}
190
191void T9InputServerMethod::SetMode(T9Mode mode)
192{
193  BAutolock l(fLocker);
194  BMenuItem *item;
195  // XXX: check
196  fMode = mode;
197  item = fDeskbarMenu->FindMarked();
198  if (item)
199    item->SetMarked(false);
200  item = fDeskbarMenu->ItemAt((int32)mode);
201  if (item)
202    item->SetMarked(true);
203  // necessary to update the copy used by the Deskbar icon.
204  SetMenu(fDeskbarMenu, BMessenger(this));
205}
206