root/src/add-ons/input_server/methods/t9/DictionaryInputServerMethod.cpp
/*
        Copyright 2005, Francois Revol.   All Rights Reserved.
        This file may be used under the terms of the Be Sample Code License.
*/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include <Debug.h>
#include <List.h>
#include <Message.h>
#include <OS.h>

#include <Application.h>
#include <Alert.h>
#include <Menu.h>
#include <MenuItem.h>
#include <Handler.h>
#include <Locker.h>
#include <Autolock.h>


#include <add-ons/input_server/InputServerMethod.h>

#ifndef _T
#define _T(s) s
#endif

#include "T9Icon.h"

extern "C" _EXPORT BInputServerMethod* instantiate_input_method();

enum T9Mode {
  WordMode,
  CharMode,
  NumMode
};


// modes: =Abc / Abc / 123
// flags:  Abc / ABC / abc

class T9InputServerMethod : public BInputServerMethod, public BHandler
{
public:
  T9InputServerMethod();
  virtual ~T9InputServerMethod();
  virtual filter_result Filter(BMessage *message, BList *outList);
  virtual status_t MethodActivated(bool active);
  virtual void MessageReceived(BMessage *message);
  
  bool IsEnabled() const { return fEnabled; };
  T9Mode Mode() const { return fMode; };
  void SetMode(T9Mode mode);
private:
  bool fEnabled;
  T9Mode fMode;
  BMenu *fDeskbarMenu;
  BLocker fLocker;
  BString fTyped; /* what has been typed so far for the current word */
};




BInputServerMethod* instantiate_input_method()
{
        PRINT(("%s\n", __FUNCTION__));
        return (new T9InputServerMethod());
}


T9InputServerMethod::T9InputServerMethod()
  : BInputServerMethod("T9", T9IconData),
    BHandler("T9IMHandler"),
    fEnabled(false),
    fMode(WordMode),
    fDeskbarMenu(NULL),
    fLocker("T9IM")
{
        PRINT(("%s\n", __FUNCTION__));

        if (be_app) {
          be_app->Lock();
          be_app->AddHandler(this);
          be_app->Unlock();
        }
        
        //
        fDeskbarMenu = new BMenu(_T("Mode"));
        
        
        BMessage *msg = new BMessage('SetM');
        msg->AddInt32("t9mode", WordMode);
        BMenuItem *item;
        item = new BMenuItem(_T("Word mode"), msg);
        item->SetMarked(true);
        fDeskbarMenu->AddItem(item);
        msg = new BMessage('SetM');
        msg->AddInt32("t9mode", CharMode);
        item = new BMenuItem(_T("Character mode"), msg);
        fDeskbarMenu->AddItem(item);
        msg = new BMessage('SetM');
        msg->AddInt32("t9mode", NumMode);
        item = new BMenuItem(_T("Numeric mode"), msg);
        fDeskbarMenu->AddItem(item);
        fDeskbarMenu->SetFont(be_plain_font);
        // doesn't seem to work here
        //fDeskbarMenu->SetRadioMode(true);
        //fDeskbarMenu->SetLabelFromMarked(true);
        
        SetMenu(fDeskbarMenu, BMessenger(this));
}

T9InputServerMethod::~T9InputServerMethod()
{
        PRINT(("%s\n", __FUNCTION__));
        SetMenu(NULL, BMessenger());
        delete fDeskbarMenu;
        if (be_app) {
          be_app->Lock();
          be_app->RemoveHandler(this);
          be_app->Unlock();
        }
}

filter_result T9InputServerMethod::Filter(BMessage *message, BList *outList)
{
        status_t err;
        filter_result res = B_DISPATCH_MESSAGE;
        bool keyUp = false;
        BString bytes;

        if (!IsEnabled())
                return B_DISPATCH_MESSAGE;

        switch (message->what) {
        case B_KEY_UP:
          keyUp = true;
        case B_KEY_DOWN:
          if (message->FindString("bytes", &bytes) < B_OK)
            break;
          if (bytes.Length() == 1) {
            BAutolock l(fLocker);
            
            if (fMode == NumMode)
              break;
          }
          break;
        default:
          break;
        }
        
        return (res);
}

status_t T9InputServerMethod::MethodActivated(bool active)
{
  fEnabled = active;
  return BInputServerMethod::MethodActivated(active);
}

void T9InputServerMethod::MessageReceived(BMessage *message)
{
  int32 v;
  switch (message->what) {
  case 'SetM':
    if (message->FindInt32("t9mode", &v) < B_OK)
      break;
    SetMode((T9Mode)v);
    
    /*{
      BString s;
      s << v;
      s << " - ";
      s << (long) fDeskbarMenu->FindMarked();
      s << " - ";
      s << (long) fDeskbarMenu->ItemAt(v);
      BAlert *a = new BAlert("Plop", s.String(), "OK");
      a->SetFlags(a->Flags() | B_CLOSE_ON_ESCAPE);
      a->Go(NULL);
      }*/
    break;
  default:
    BHandler::MessageReceived(message);
    break;
  }
}

void T9InputServerMethod::SetMode(T9Mode mode)
{
  BAutolock l(fLocker);
  BMenuItem *item;
  // XXX: check
  fMode = mode;
  item = fDeskbarMenu->FindMarked();
  if (item)
    item->SetMarked(false);
  item = fDeskbarMenu->ItemAt((int32)mode);
  if (item)
    item->SetMarked(true);
  // necessary to update the copy used by the Deskbar icon.
  SetMenu(fDeskbarMenu, BMessenger(this));
}