text: /*
  ** $Id: pinyin_kbd.c 1007 2008-08-31 04:00:18Z houhuihua $
  **
  ** pinyin.c: This file include pinyin soft keyboard code. 
  **
  ** Copyright (C) 2003 ~ 2008 Feynman Software.
  ** Copyright (C) 1999 ~ 2002 Wei Yongming.
  **
  ** Create date: 2008/07/15
  **
  */
  
  
  #include "common.h"
  #include "libime/ime.h"
  
  #ifdef KBD_TOOLTIP
  #include "tooltip.h"
  #endif
  
  static char fontname[32] = {0};
  
  static void make_font(void)
  {
  #if 0
  	static DEVFONT *devfont;
  	int i;
  	int j;
  
  
  #if (MINIGUI_MAJOR_VERSION > 2)
      InitFreetypeLibrary ();
  	devfont = LoadDevFontFromFile("ttf-noname-rrncnn-0-0-ISO8859-1",
  			"ttf-fonts/cn.ttf");
  #else
  	InitFreeTypeFonts ();
  	LoadDevFontFromFile("ttf-noname-rrncnn-0-0-ISO8859-1",
  			"ttf-fonts/cn.ttf", &devfont);
  #endif
  	
  	if(devfont && devfont->name) {
  		for(i=0; devfont->name[i] != '-' 
  				&& devfont->name[i] != 0; i++);
  
  		for(i++, j=0; devfont->name[i] != '-' 
  				&& devfont->name[i] != 0; i++,j++) {
  			fontname[j] = devfont->name[i];
  		}
  	}
  #endif
  }
  
  static md_key_t py_key_pads[] = { 
      { RECT_EN_KEY_1 , 'q', SCANCODE_Q,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_2 , 'w', SCANCODE_W,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_3 , 'e', SCANCODE_E,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_4 , 'r', SCANCODE_R,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_5 , 't', SCANCODE_T,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_6 , 'y', SCANCODE_Y,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_7 , 'u', SCANCODE_U,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_8 , 'i', SCANCODE_I,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_9 , 'o', SCANCODE_O,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_10, 'p', SCANCODE_P,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_11, 'a', SCANCODE_A,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_12, 's', SCANCODE_S,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_13, 'd', SCANCODE_D,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_14, 'f', SCANCODE_F,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_15, 'g', SCANCODE_G,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_16, 'h', SCANCODE_H,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_17, 'j', SCANCODE_J,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_18, 'k', SCANCODE_K,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_19, 'l', SCANCODE_L,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_20, ' ', SCANCODE_LEFTSHIFT,  KEY_PAD_FUNC, NULL, share_key_update},
      { RECT_EN_KEY_21, 'z', SCANCODE_Z,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_22, 'x', SCANCODE_X,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_23, 'c', SCANCODE_C,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_24, 'v', SCANCODE_V,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_25, 'b', SCANCODE_B,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_26, 'n', SCANCODE_N,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_27, 'm', SCANCODE_M,          KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_28, ' ', SCANCODE_BACKSPACE,  KEY_PAD_FUNC, NULL, share_key_update},
      { RECT_EN_KEY_29, ' ', SCANCODE_TONUM,      KEY_PAD_FUNC, NULL, share_key_update},
      { RECT_EN_KEY_30, ' ', SCANCODE_TOEN,       KEY_PAD_FUNC, NULL, share_key_update},
      { RECT_EN_KEY_31, ' ', SCANCODE_SPACE,      KEY_PAD_CHAR, NULL, share_key_update},
      { RECT_EN_KEY_32, ' ', SCANCODE_ENTER,      KEY_PAD_FUNC, NULL, share_key_update},
  };
  
  static md_ime_t py_ime =
  {
      100,
      "pinyin",
      NULL,
  	cb_pinyin_translate_word,
  	cb_pinyin_predict_word,
  	cb_pinyin_init
  };
  
  static md_key_t* get_py_key (key_window_t *kw, POINT point)
  {
      int i;
      md_key_t* keys = kw->key;
  
      for(i = 0; i < kw->key_num; i++)
      {
          if (hit_rect( keys[i].bound, point))
              return &keys[i];
      }
  
      return NULL;
  }
  
  static void kw_update (key_window_t *kw, HWND hWnd)
  {
      //TODO
      //printf("==== update key window ====\n");
  }
  
  static void sw_update (stroke_window_t *sw, HWND hWnd)
  {
      HDC hdc;
      PLOGFONT old_font;
      gal_pixel old_tecolor;
  
      EraseBbGround(hWnd, &sw->bound);
      if (strlen(sw->str) != 0)
      {
          hdc = GetDC(hWnd);
          
          SetBkMode (hdc, BM_TRANSPARENT);
          old_tecolor = SetTextColor (hdc, PIXEL_lightwhite);
          old_font = SelectFont(hdc, sw->stroke_font);
          DrawText (hdc, sw->str, -1, &(sw->bound), DT_LEFT);
          SelectFont(hdc, old_font);
          SetTextColor(hdc, old_tecolor);
          
          ReleaseDC(hdc);
      }
  }
  
  static void vw_update (view_window_t *vw, HWND hWnd, vw_element_t* element)
  {
  	int i;
  	RECT r;
      PBITMAP pbmp;
  	static int old_style = 0;
  	HDC hdc = GetDC(hWnd);
  	RECT rc;
      PLOGFONT oldfont;
  
  	r.left = vw->key_pg_up.right;
  	r.top  = vw->bound.top;
  	r.right = vw->key_pg_down.left;
  	r.bottom = vw->bound.bottom;
  
  	oldfont = SelectFont(hdc, vw->view_font);
  	SetBkMode (hdc, BM_TRANSPARENT);
  	if(vw->style & VW_DRAW_ELMTS) {
  		if(element == NULL) {
  			element = vw->elements;
              EraseBbGround(hWnd, &r);
  			for(i=0; i<vw->element_num; i++) {
  #ifndef __FILL_DIRECT__ 
  				SetTextColor(hdc, RGB2Pixel(hdc, 190, 190, 190));
  				DrawText(hdc, element[i].string, -1, &element[i].bound, 0);
  
  				rc = element[i].bound;
  				rc.top --; 
  				rc.bottom --;
  				rc.left --; 
  				rc.right --;
  				SetTextColor(hdc, RGB2Pixel(hdc, 155, 50, 155));
                  DrawText(hdc, element[i].string, -1, &rc, 0);
  #else
                  DrawText(hdc, element[i].string, -1, &element[i].bound, 0);
  #endif
  			}
  		} else {
  			if(vw->style & VW_EL_PRESSED) {
                  if (vw->data)
  #ifdef __FILL_DIRECT__
  	#if 0
                      FillBoxWithBitmap(hdc,element->bound.left, 
  							element->bound.top,
                              element->bound.right - element->bound.left,
                              element->bound.bottom - element->bound.top,
                              &(((vw_add_data_t *)(vw->data))->sel_bk) );
  	#else
  				//SetBrushColor(hdc, RGB2Pixel(hdc, 120, 187, 250));
  				SetBrushColor(hdc, RGB2Pixel(hdc, 61, 89, 160));
                  FillBox(hdc,element->bound.left, element->bound.top,
                              element->bound.right - element->bound.left,
                              element->bound.bottom - element->bound.top);
  	#endif
  				SetTextColor(hdc, COLOR_lightwhite);
                  DrawText(hdc, element->string, -1, &element->bound, 0);
  #else
  				rc = element->bound;
  				rc.top --; 
  				rc.left --; 
                  EraseBbGround(hWnd, &rc);
  				rc.top += 2; 
  				rc.left += 2; 
  				rc.bottom ++;
  				rc.right ++;
  				SetTextColor(hdc, RGB2Pixel(hdc, 100, 50, 100));
                  DrawText(hdc, element->string, -1, &rc, 0);
  #endif
  			} else {
                  EraseBbGround(hWnd, &vw->bound);
  			}
  
  		}
      } else if(old_style & VW_DRAW_ELMTS) {
          EraseBbGround(hWnd, &r);
      }
  
      EraseBbGround(hWnd, &vw->key_pg_up);
  
  	if(vw->style & VW_SHOW_PU) {
  		if(vw->style & VW_PU_PRESSED) {
              pbmp = &(((vw_add_data_t *)(vw->data))->pu_press);
  		} else {
              pbmp = &(((vw_add_data_t *)(vw->data))->pu_normal);
  		}
          FillBoxWithBitmap (hdc, vw->key_pg_up.left, vw->key_pg_up.top,
                  vw->key_pg_up.right-vw->key_pg_up.left,
                  vw->key_pg_up.bottom-vw->key_pg_up.top, pbmp);
  	}
      
      EraseBbGround(hWnd, &vw->key_pg_down);
  	
      if(vw->style & VW_SHOW_PD) {
  		if(vw->style & VW_PD_PRESSED) {
              pbmp = &(((vw_add_data_t *)(vw->data))->pd_press);
  		} else {
              pbmp = &(((vw_add_data_t *)(vw->data))->pd_normal);
  		}
          FillBoxWithBitmap (hdc, vw->key_pg_down.left, vw->key_pg_down.top,
                  vw->key_pg_down.right-vw->key_pg_down.left,
                  vw->key_pg_down.bottom-vw->key_pg_down.top, pbmp);
  	}
  	
      old_style = vw->style;
  	//SelectFont(hdc, oldfont);
  	ReleaseDC(hdc);
  }
  
  int pinyin_proceed_msg(key_board_t* key_board, HWND hwnd,
  		int message, WPARAM wParam, LPARAM lParam) 
  {
  	static RECT old_hit_rect; 
  	static int lbuttondown = 0;
  	static POINT p;
  
  	switch(message) {
  		case MSG_LBUTTONDOWN:
  			p.x = LOSWORD(lParam);
  			p.y = HISWORD(lParam);
  			lbuttondown = 1;
  			key_board->action.operation = AC_NULL; 
  
  			if(hit_rect(key_board->view_window->bound, p)) {
  				vw_proceed_hit(hwnd, key_board->view_window,
  						key_board->stroke_window, &key_board->action,
  						TRUE, p, CN, key_board->ime);
  				break;
  			}
  
  			if(hit_rect(key_board->key_window->bound, p)) {
  				md_key_t* key = key_board->key_window->get_key
  					(key_board->key_window, p);
  				if(key == NULL) {
  					key_board->action.operation = AC_NULL; 
  					break;
  				}
  
  				kw_proceed_hit(hwnd, key_board->view_window,
  						key_board->stroke_window, key, &key_board->action,
  						TRUE, p, CN, key_board->ime, wParam, lParam);
  
  				break;
  			}
  
  			break;
  		case MSG_LBUTTONUP: 
  			if (lbuttondown == 0) {
  				key_board->action.operation = AC_NULL; 
  				break; 
  			}
  
  			lbuttondown = 0;
  			p.x = LOSWORD(lParam);
  			p.y = HISWORD(lParam);
  
  			if (hit_rect(key_board->close_rc, p)) {
  				key_board->action.operation = AC_NULL; 
                  SendMessage (hwnd, MSG_IME_CLOSE, 0, 0);
                  return AC_NULL;
              }
  			
  			if(hit_rect(key_board->view_window->bound, p)) {
  				vw_proceed_hit(hwnd, key_board->view_window,
  						key_board->stroke_window, &key_board->action,
  						FALSE, p, CN, key_board->ime);
  				break;
  			} 
  			
  			if(hit_rect(key_board->key_window->bound, p)) {
  				md_key_t* key = key_board->key_window->get_key
  					(key_board->key_window, p);
  				if(key == NULL) {
  					key_board->action.operation = AC_NULL; 
  					break;
  				}
  
  				kw_proceed_hit(hwnd, key_board->view_window,
  						key_board->stroke_window, key, &key_board->action,
  						FALSE, p, CN, key_board->ime, wParam, lParam);
  
  				break;
  			}
  			break;
  
  		case MSG_MOUSEMOVE:
  			p.x = LOSWORD(lParam);
  			p.y = HISWORD(lParam);
  			proceed_move(hwnd, key_board, lbuttondown, p, EN);
  			break;
  		case MSG_MOUSEMOVEIN:
  			lbuttondown = lbuttondown && wParam;
  			break;
  	}
  
  	return key_board->action.operation; 
  }
  
  static int init_py_view_window (HWND hWnd, view_window_t *vw)
  {
      vw->bound.left          = SKB_VW_L   ;
      vw->bound.top           = SKB_VW_T + 2;
      vw->bound.right         = SKB_VW_R   ;
      vw->bound.bottom        = SKB_VW_B   ;
                                           
  	vw->key_pg_up.left      = SKB_VW_PU_L;
  	vw->key_pg_up.top       = SKB_VW_PU_T;
  	vw->key_pg_up.right     = SKB_VW_PU_R;
  	vw->key_pg_up.bottom    = SKB_VW_PU_B;
                                           
  	vw->key_pg_down.left    = SKB_VW_PD_L;
  	vw->key_pg_down.top     = SKB_VW_PD_T;
  	vw->key_pg_down.right   = SKB_VW_PD_R;
  	vw->key_pg_down.bottom  = SKB_VW_PD_B;
  	
  #ifdef SOFTKBD_320_240 
  	vw->max_str_len = 22;
  #elif defined (SOFTKBD_480_272)   
  	vw->max_str_len = 40;
  #elif defined (SOFTKBD_240_320)   
  	vw->max_str_len = 20;
  #endif 
  
      vw->update = vw_update;
      vw->set_elements = vw_set_elements;
      vw->clear_elements = vw_clear_elements;
      vw->get_element = vw_get_element;
  
  
  	vw->view_font = CreateLogFontByName ("*-fixed-rrncnn-*-12-GB2312");
  #if 0
  	vw->view_font = CreateLogFontByName (NULL, fontname, "GB2312",
  			FONT_WEIGHT_BOLD,
  			FONT_SLANT_ROMAN,
  			FONT_FLIP_NIL,
  			FONT_OTHER_NIL, 
  			FONT_UNDERLINE_NONE, 
  			FONT_STRUCKOUT_NONE, 
  			12, 0);
  #endif
      if (NULL == vw->view_font){
          _MY_PRINTF("create logfont for view window error.\n");
          return -1;
      }
  
      if (NULL == (vw->data = (void *)calloc (1, sizeof(vw_add_data_t)))){
          _MY_PRINTF("no memory for key window add data.\n");
          return -1;
      }
      
      if (get_kbd_bitmap(HDC_SCREEN, 
                  &(((vw_add_data_t *)(vw->data))->pu_normal),
  				LEFT_ARROW_ENABLE)) {
          _MY_PRINTF ("Fail to get page-up mask bitmap.\n");
          return -1;
      }
  
      if (get_kbd_bitmap(HDC_SCREEN, 
                  &(((vw_add_data_t *)(vw->data))->pu_press),
  				LEFT_ARROW_DISABLE)) {
          _MY_PRINTF ("Fail to get page-up mask bitmap.\n");
          return -1;
      }
  
      if (get_kbd_bitmap(HDC_SCREEN, 
                  &(((vw_add_data_t *)(vw->data))->pd_normal),
  				RIGHT_ARROW_ENABLE)) {
          _MY_PRINTF ("Fail to get page-down mask bitmap.\n");
          return -1;
      }
  
      if (get_kbd_bitmap(HDC_SCREEN, 
                  &(((vw_add_data_t *)(vw->data))->pd_press),
  				RIGHT_ARROW_DISABLE)) {
          _MY_PRINTF ("Fail to get page-down mask bitmap.\n");
          return -1;
      }
  /*
      if (get_kbd_bitmap(HDC_SCREEN, 
                  &(((vw_add_data_t *)(vw->data))->sel_bk), 
  				SELECT_TEXT_BKGND)) {
          _MY_PRINTF ("Fail to get sellect text bkgnd bitmap.\n");
          return -1;
      }
  */
      return 0;
  }
  
  static void destroy_py_view_window (view_window_t *vw)
  {
  
      if (vw->data)
      {
          release_kbd_bitmap(&(((vw_add_data_t *)(vw->data))->pu_normal));
          release_kbd_bitmap(&(((vw_add_data_t *)(vw->data))->pu_press));
          release_kbd_bitmap(&(((vw_add_data_t *)(vw->data))->pd_normal));
          release_kbd_bitmap(&(((vw_add_data_t *)(vw->data))->pd_press));
          release_kbd_bitmap(&(((vw_add_data_t *)(vw->data))->sel_bk));
          free(vw->data);
      }
  
      if (vw->view_font){
          DestroyLogFont(vw->view_font);	
      }
  }
  
  static int init_py_stroke_window (HWND hWnd, stroke_window_t *sw)
  {
      sw->bound.left   = SKB_SW_L;
      sw->bound.top    = SKB_SW_T;
      sw->bound.right  = SKB_SW_R;
      sw->bound.bottom = SKB_SW_B;
      
      memset(sw->str, 0, SW_STR_LEN);
  
  #if 0
      sw->stroke_font = CreateLogFont (NULL, "times", "ISO8859-1", 
                          FONT_WEIGHT_BOOK, FONT_SLANT_ROMAN, 
                          FONT_SETWIDTH_NORMAL, FONT_OTHER_NIL, 
                          FONT_UNDERLINE_NONE, FONT_STRUCKOUT_NONE, 
                          9, 0);
  #endif
  	sw->stroke_font = CreateLogFontByName ("*-times-rrncnn-*-9-ISO8859-1");
      if (NULL == sw->stroke_font){
          _MY_PRINTF("create logfont for stroke window error.\n");
          return -1;
      }
  
      sw->update = sw_update;
  
      return 0;
  }
  
  static void destroy_py_stroke_window (stroke_window_t *sw)
  {
      if (sw->stroke_font)
          DestroyLogFont (sw->stroke_font);
      
      return;
  }
  
  static int init_py_key_window (HWND hWnd, key_window_t *kw)
  {
      int i;
      md_key_t *key;
  
      kw->bound.left   = SKB_KW_L;
      kw->bound.top    = SKB_KW_T;
      kw->bound.right  = SKB_KW_R;
      kw->bound.bottom = SKB_KW_B;
      
      kw->press.x = 0;
      kw->press.y = 0;
  
      kw->key = py_key_pads;
      kw->key_num = TABLESIZE(py_key_pads);
  
      kw->get_key = get_py_key;
  
      if (NULL == (kw->data = (void *)calloc (1, sizeof(kw_add_data_t)))){
          _MY_PRINTF("no memory for key window add data.\n");
          return -1;
      }
  
      if (get_kbd_bitmap(HDC_SCREEN, 
                  &(((kw_add_data_t *)(kw->data))->char_key_press),
  				CHAR_KEY_MASK)) {
          _MY_PRINTF ("Fail to get py char key mask bitmap.\n");
          return -1;
      }
  
      if (get_kbd_bitmap(HDC_SCREEN, 
                  &(((kw_add_data_t *)(kw->data))->func_key_press),
  				FUNC_KEY_MASK)) {
          _MY_PRINTF ("Fail to get py func key mask bitmap.\n");
          return -1;
      }
  
      kw->update = kw_update;
  
      /*use the shared bitmap for press key painting.*/
      key = kw->key;
      for (i = 0; i < kw->key_num; i++){
          if(key->style == KEY_PAD_CHAR)
              key->data = &(((kw_add_data_t *)(kw->data))->char_key_press);
          else
              key->data = &(((kw_add_data_t *)(kw->data))->func_key_press);
          key++;
      } 
      return 0;
  }
  
  static void destroy_py_key_window (key_window_t *kw)
  {
      if (kw->data)
      {
          release_kbd_bitmap(&(((kw_add_data_t *)(kw->data))->char_key_press));
          release_kbd_bitmap(&(((kw_add_data_t *)(kw->data))->func_key_press));
          free(kw->data);
      }
  }
  
  int init_py_keyboard (HWND hWnd, key_board_t *kb)
  {
  	make_font();
  
      kb->close_rc.left   = SKB_CLOSE_L;
      kb->close_rc.top    = SKB_CLOSE_T;
      kb->close_rc.right  = SKB_CLOSE_R;
      kb->close_rc.bottom = SKB_CLOSE_B;
  
      /*initalize for view window.*/
      kb->view_window = (view_window_t *)calloc(1, sizeof(view_window_t));
      if(kb->view_window == NULL){
          _MY_PRINTF("no memory for view window.\n");
          return -1;
      }
      if (0 != init_py_view_window (hWnd, kb->view_window)){
          _MY_PRINTF("error for initalizing view window.\n");
          return -1;
      }
      
      /*initalize for stroke window.*/
      kb->stroke_window = (stroke_window_t *)calloc(1, sizeof(stroke_window_t));
      if(kb->stroke_window == NULL){
          _MY_PRINTF("no memory for view window.\n");
          return -1;
      }
  
      if (0 != init_py_stroke_window (hWnd, kb->stroke_window)){
          _MY_PRINTF("error for initalizing stroke window.\n");
          return -1;
      }
      
      /*initalize for key window.*/
      kb->key_window = (key_window_t *)calloc(1, sizeof(key_window_t));
      if(kb->key_window == NULL){
          _MY_PRINTF("no memory for key window.\n");
          return -1;
      }
      if (0 != init_py_key_window (hWnd, kb->key_window)){
          _MY_PRINTF("error for initalizing key window.\n");
          return -1;
      }
     
      /*initalize for bk image.*/
      kb->data = calloc (1, sizeof(BITMAP));
      if(kb->data == NULL){
          _MY_PRINTF("no memory for bk image.\n");
          return -1;
      }
  
      if (get_kbd_bitmap(HDC_SCREEN, (PBITMAP)(kb->data), PINYIN_KBD_BKG)) {
          _MY_PRINTF ("Fail to get pinyin kbd bkgnd bitmap.\n");
          return -1;
      }
  
      kb->update = keyboard_update;
  
      kb->ime = &py_ime;
  	kb->ime->init(NULL);
  
      memset (&(kb->action), 0, sizeof(action_t));
      
      kb->proceed_msg = pinyin_proceed_msg;
  
      return 0;
  }
  
  void destroy_py_keyboard (key_board_t *kb)
  {
      /*view window*/
      destroy_py_view_window (kb->view_window);
      free(kb->view_window);
  
      /*stroke window*/
      destroy_py_stroke_window (kb->stroke_window);
      free(kb->stroke_window);
  
      /*ky window*/
      destroy_py_key_window (kb->key_window);
      free(kb->key_window);
  
      /*add data*/
      release_kbd_bitmap((PBITMAP)(kb->data));
      free(kb->data);
  }
  