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