²z xcin Jk module [cAHηsW module kC

A. [c (include/module.h, include/imodule.h, include/cinput.h, module.c):

   module ]pتOƱ programmer iHܮea[JsJk䴩A]
   ڤwɶqNӳ:

	1. programmer interface (module.h)
	2. internal implementation (imodule.h)

   Programmer iHz| internal Ӹ`ALuݭnN module.h Yw
   q module_t ƵcnYiCi঳ǤH internal Ӹ`A
   G`Ny@C

   ҿסumodule JγQMΡvOӶqAΥHUҤl:

   ҦpYϥΪ̫U ctrl+alt+1 Ұ cj(ܾe) JkAh xcin |䤺
   cinput ChӿJkñҰʥAwqpU:

=========================================================================
typedef struct cinput_s  cinput_t;
struct cinput_s {
    char *modname;
    char *objname;
    imodule_t *inpmod;
};

cinput_t cinput[MAX_INP_ENTRY];
=========================================================================

   ] xcin  rcfile ]wAϥΪ̦Uϥ cj JkABӿJk
   M gen_inp module,  setkey O 1, ӿJk٨SQJAh cinput 
   epU:

	cinput[1].modname = "gen_inp";
	cinput[1].objname = "cj";
	cinput[1].inpmod = NULL;

   䤤 inpmod OuwJBwM cj oӿJk module, YȤO NULL, 
   ܸӿJkwgJBiHϥΡAh xcin |WϥΥCϤA xcin N
   i汵UӪJu@C

   o xcin | tmodule_t *mod_templet; o list MݦS "gen_inp"
   o module uMҡvC tmodule_t Owqb imodule.h Aݩ internal
   CpGFAhMΡAoɵ{|ھ tmodule_t TA
   @ imodule_t (wqb imodule.h) cA conf data structer,
   object name  "cj", YM cj JkCB cinput[1].inpmod ]|
   VoӷsͥXӪ imodule_t cC

   U@b mod_templet 䤣 "gen_inp" ܡANn dlopen() ۵wЪ 
   gen_inp.so ɸJFCJAN|[J mod_templet list YAMA
   X@ boshiamy Jk imodule_t ӨϥΡC

   oثܭnO: @ module O@ӹB@ (object), uOӮMҡAO
   ǳƳQYӿJkӮMΪA@ module MҥiHQhؤPJkMΡC
   ]Ab module wqA䥻ƵcOsbAӬOnQYӿ
   JkM (Y imodue_t) ɡAtΤ~| malloc() @ŶƵcA
   å rcfile ŪtŪJ]w (ШHU)C



B. Ƶc (include/module.h):

   n[JsJk module, zunnpUƵcügn禡Yi:

=================================  module.h  ==============================
typedef struct module_s  module_t;
struct module_s {
    char *name;
    char *version;
    char *comments;
    char **valid_objname;
    enum mtype module_type;

    int conf_size;
    int (*init) (void *conf, char *objname, core_config_t *xc);
        /* called when IM first loaded & initialized. */
    int (*xim_init) (void *conf, inpinfo_t *inpinfo);
        /* called when trigger key occures to switch IM. */
    unsigned (*xim_end) (void *conf, inpinfo_t *inpinfo);
        /* called just before xim_init() to leave IM, not necessary */
    int (*switch_in) (void *conf, inpinfo_t *inpinfo);
        /* called when set_focus_in, not necessary */
    int (*switch_out) (void *conf, inpinfo_t *inpinfo);
        /* called when set_focus_out, not necessary */
    unsigned (*keystroke) (void *conf, inpinfo_t *inpinfo, keyinfo_t *keyinfo);
        /* called to input key code, and output chinese char. */
    int (*show_keystroke) (void *conf, simdinfo_t *simdinfo);
        /* called to show the key stroke */
};
=============================================================================

   Ъ`NAѩ xcin ĥΪO module QJkMΡA[WC@ IC (Input 
   Context, Ш structer @媺) JAWߪ]pAGJ
   kb xcin ҧtNnO@ server, RRaݨӦ xcin
   ШDAðX^C]AҦJk module Ƶc
   : ӿJkγ]wA void *conf ܼƶǤJWz module 禡F
   t@ӬOC IC JAơAoاڭ̨èSN IC cǤJ module
   禡ءAO] IC cٲoAܦhP XIM Ӹ`AӧڧƱCӿ
   Jk module iHPoǲӸ`LAGbON inpinfo_t *inpinfo ǤJ
   ( show_keystroke ӨǤJO simdinfo_t *simdinfo), inpinfo o
   Ƶc]tFثe xcin APJkTAOG̶q޹DC


   1. ӿJkγ]w:

      oǳ]wDnOq rcfile ŪtΪƩҳ]wAPɤ]iHΨӫOs
      xim_init() IsɨӦ core_config_t *xc (Y xcin_conf) һݪơC
      |@ӨҤl:

============================================================================
(define cj
        '((SETKEY         1)
          (AUTO_COMPOSE   YES)
          (AUTO_UPCHAR    YES)
          (AUTO_FULLUP    NO)
          (SPACE_AUTOUP   NO)
          (SELKEY_SHIFT   NO)
          (SPACE_IGNORE   NO)
          (SPACE_RESET    YES)
          (AUTO_RESET     NO)
          (END_KEY        NO)
          (WILD_ENABLE    NO)
          (AUTO_SELECT    NO)
          (SINMD_IN_LINE1 NO)
          (BEEP_WRONG     YES)
          (BEEP_DUPCHAR   YES)))
============================================================================

      Wz]wObҰ xcin AXU (Φb IC U) ۦPC
      ѩ cj oӿJkM "gen_inp" module, B "gen_inp" module
      ]iHQLJkҮMΡAOJkbMΫAWzγ]wȤ
      oP cj Jk@ˡCyܻA\hJkiHM "gen_inp"
      module, ϥθ module 禡P\AUOJkγ]wƵc
      }C

      ]AbWY module_t ƵcASuγ]wϡvAۤϪ
      ڭ̦uγ]wϤjpv: int conf_size; oO programmer 
      wA]CӤPJk module 䤽γ]wϸƵciण@ˡC
      tη| module uQYӿJkMΫA~|ھ conf_size 
       module (Jk) t@WߪθƵcϰC

      ܩ module 禡npϥΤθƵcO? UiHݨCӨ禡
      @ void *conf A]NOӸƵc|gѦǤJCWҭzA
      ڭ̦bg{ɡAڭ̥uHUd:

============================================================================
typedef struct {		/* oO module ۩wθƵc */
    char *inpname;
    int  setkey;
    ...........
} my_module_datastr_t;

int my_module_init(void *conf, char *objname, core_config_t *xc)
/* oO module  init() 禡 */
{
    my_module_datastr_t *cf = (my_module_datastr_t *)conf;

    cf->inpname = .....;
    cf->setkey = .....;
}

.................

module_t module_ptr = {
    ......
    sizeof(my_module_datastr_t),	/* oO conf_size  */
    ......
    my_module_init,			/* oO init  */
};
============================================================================

      Ъ`NA̫᪺ module_ptr oӦWrOSA@wnγoӦWrAo
      xcin bϥ dlopen() J module ɡA~ module_t YC
      C


   2. C IC JA:

      C IC JAƬOѦUOJk module P xcin tΦ@P@C
      C X window ǳƱ xcin JɡA xcin N|ͤ@ IC
      Pɤ]|@ inpinfo_t Ƶcxs IC JA:

=============================================================================
typedef struct inpinfo_s  inpinfo_t;
struct inpinfo_s {
    int icid;                           /* ID of current Input Context */
    void *iccf;                         /* Internal data of IM for each IC */

    char *inp_cname;                    /* IM Chinese name */
    char *inp_ename;                    /* IM English name */
    unsigned char area3_len;            /* Length of area 3 of window (n_char)*/
    unsigned short xcin_wlen;           /* xcin window length */
    unsigned short guimode;             /* GUI mode flag */

    unsigned char keystroke_len;        /* # chars of keystroke */
    wch_t *s_keystroke;                 /* keystroke printed in area 3 */

    unsigned short n_selkey;            /* # of select keys */
    wch_t s_selkey[SELECT_KEY_LENGTH+2];/* the displayed select keys */
    unsigned short n_mcch;              /* # of chars with the same keystroke */
    wch_t mcch[SELECT_KEY_LENGTH];      /* multi-char list */
    char mcch_pgstate;                  /* page state of multi-char */

    wch_t cch_publish;                  /* A published cch. */
    unsigned short n_lcch;              /* # of composed cch list. */
    wch_t *lcch;                        /* composed cch list. */
    unsigned short edit_pos;            /* editing position in lcch list. */
    char *cch;                          /* the string for commit. */
};
=============================================================================

      ӦƵ|ǤJYǯSw module 禡 (p keystroke() 禡)A
      module ѻPBzCC쪺NqpU:

      icid:  ثeϥΥJk module  IC sC

      iccf:  ɭԷJkҲջݭnC@ IC UO͸ƵcɡAh
	  Ӱk: @OۦbӿJkγ]w ( 1 I) ۦ@@
	   IC ƦCAMǥ icid ӵOoǸƦCOݩ󨺨 ICC
	  t@Ӹ²檺kOQ iccf oӫСAثe IC ݪ
	  ƵcAhCY IC QϥήɡA iccf N۵Mݪ
	  cFC

	  Ъ`NA xcin |z@ЩҫƵcAGznΦ
	  ЮɡAۦTwTuƵcWAӥBѩ inpinfo
	  O_Jk@ΪAGzTwCbJkڡA iccf 
	  VOTC@²檺kOb xim_init() (z)  malloc
	  @Ӱϰ쵹 iccf, Ӧb xim_end() (z) N free C

      inp_cname:  JkWC

      inp_ename:  Jk^WC

      area3_len:  զrϤjp (: ^rӼ)

      xcin_wlen:  oO xcin ҳ]wAΨӧiDJkҲեثe xcin 
	  סC

      guimode:  JkҲեiHγoܼƨӳ]w GUI tίSwܪA:

	  GUIMOD_SELKEYSPOT:  ثeJkBhrܮɡA]wiHq
		GUI tάO_NCӿ㲴C (Spot light) ܡC

	  GUIMOD_SINMDLINE1:  ]wiHq GUI tΦbLXuJkrXv
		ɡAObӦmLXA٬ObĤ@LXC

	  GUIMOD_LISTCHAR:  Y]w on, h GUI tη|b xcin Ĥ@
		LX inpinfo->lcch rꪺeAîھ inpinfo->edit_pos
		eXЦmAoOΩ bimsphone ҲաAJrɡA
		rä|W] client ءAӬOdb xcin 
		Ĥ@AӴЫhܤFثeJmC

      keystroke_len:  ثewJrXסC

      s_keystroke:  ثewJrXAYNܦb xcin ĤGĤG
		ϪeCЪ`N xcin |@wİϪeAGU
		Jkۦ@AШe iccf C

      n_selkey:  Jkhr䪺ӼơC

      s_selkey:  JkhrCC

      n_mcch:  ثehrӼơC

      mcch:  ثehrCAЪ`NCjpWL n_selkey ȡC

      mcch_pgstate:  ܥثehruvAA䤤u@vN xcin 
	  Ĥ@iHܪeסCȥiHpU:

	  MCCH_ONEPG:  hr`ƥiHb@ܪ̡C

	  MCCH_BEGIN:  hr`ƶWL@iܡAɥbĤ@C

	  MCCH_MIDDLE: hr`ƶWL@iܡAɥbĤ@P̫@C

	  MCCH_END:  hr`ƶWL@iܡAɥb̫@C

           xcin UܰϦmPNqAШ structer @媺C

      cch_publish:  ܥثewզrBiHuGvrCNQΨӰ
	  uJkrܡvΡAzC

      n_lcch:  lcch wİϤrӼơC

      lcch:  bimsphone ΨLu۵MvJkΨӦCܤwJr
	  wİϡAe guimode -> GUIMOD_LISTCHAR CЪ`N xcin
	  @wİϡAGUJkҲխYnϥΥɡAۦ@C
	  Шe iccf C

      edit_pos:   lcch rCثeЦmAШe
	  guimode -> GUIMOD_LISTCHAR C

      cch:  ΨӦsJkҲշǳ commit  XIM client rCЪ`N xcin
	  @wİϡAGUJkҲխYnϥΥɡAۦ@C
          Шe iccf C


C. module_t 컡:

   HUUYᦳХ (*) ̪ܥnA_hiiL (Yi] 0 
   NULL)C

   1. name (*):  ҲզW١C

   2. version (*):  

      ҲժCЪ`NtΪҲժOĥΤrAp "19990217"Ct
      JҲծɡA|ˬdҲժOOPtΪ@ˡAOܫh
      J (]OtΪҲլ[ciw) C]Azn xcin [Js
      ծɡAЪ`Nnwثe xcin ҲթwqPӼgC

   3. comments:  Ҳժ²uC

   4. valid_objname:

      wiΨӮMΦ module JkWCCC̫ᥲH@ NULL item
      CYwAhtΰ] module uQW٬ name Jk (P
      ҲզPW) ҮMΡCCW٥iH *  ? UΦrAҦp:

	{"my_inp", "my_inp_ext_*", "my_inp_ver??", NULL}

      hZOJkW٬ "my_inp", "my_inp_ext_style1", "my_inp_ext_power",
      "my_inp_ver99" .... AiHMΦҲաC

   5. module_type (*):

      ثe xcin uwq@ module_type, bг] MOD_CINPUTC

   6. conf_size (*):  Ҳժγ]wƵcjpC

   7. int (*init) (void *conf, char *objname, core_config_t *xc) (*):

      Ҳժlƨ禡AOΩӼҲղĤ@QJγQYJkMήɤ~IsC
      ȬOnҦlưʧ@APɭnN rcfile һݪŪiӡC
      UѼƷNqpU:

      conf:  Ҳժγ]wƵcСC

      objname:  MΦҲժJk^W١C

      xc:  V xcin_conf (xcin ]wƵc) СA@ЦU
            module  xcin T (p locale ]w)C

      禡Y\Ǧ^ True, ѶǦ^ FalseC


   8. int (*xim_init) (void *conf, inpinfo_t *inpinfo) (*)

      禡b@ӷs IC (s window ǳƱ xcin J) ͮɡAάY
      IC PJkɳQIsCoɥnnʧ@ IC lơA
      Pɤ]nlƦ IC JA (Y]w inpinfo)C

      Ъ`NAѩ inpinfo Oݩ IC Ƶc@AäݩU module, U 
      module uOΥӻP xcin qӤwCyܻA inpinfo OҦJk 
      module @ΪC]AYӿJkǳƳQY IC ϥήɡA IC K|Is 
      禡Ah禡 inpinfo C]w (]̥ثeȥi
      OWӨϥΥJkҲթҳ]AAΩثeJkҲ)AåB
      n malloc wİϵ inpinfo->iccf, inpinfo->s_keystroke, inpinfo->lcch,
      P inpinfo->cch ϥΡC

      禡Y\Ǧ^ True, ѶǦ^ FalseC


   9. unsigned int (*xim_end) (void *conf, inpinfo_t *inpinfo) (*)

      CY IC ɡAΤPJkɡA xcin bIst@ӿJk 
      xim_init() e|IsثeoӿJk xim_end()Cڭ̥iHb@
      eu@AҦpݭnM free  inpinfo->iccf, inpinfo->s_keystroke, 
      inpinfo->lcch, P inpinfo->cch wİ .... C

      禡Ǧ^ȥiHP keystroke() Ǧ^Ȥ@ˡAGiΩ commit rA
      zC


   10. int (*switch_in) (void *conf)

      pG禡sbܡAhC xcin ۬Y IC  XIM_SET_IC_FOCUS T
      AΪ̦bIs xim_init() AN|Is禡CY禡sbܡA
      switch_out() ]sbC

      禡Y\Ǧ^ True, ѶǦ^ FalseC


   11. int (*switch_out) (void *conf)

      pG禡sbܡAhC xcin ۬Y IC  XIM_UNSET_IC_FOCUS T
      AΪ̦bIs xim_end() eAN|Is禡CY禡sbܡA
      switch_in() ]sbC

      禡Y\Ǧ^ True, ѶǦ^ FalseC


   12. unsigned int (*keystroke) (void *conf, 
		inpinfo_t *inpinfo, keyinfo_t *keyinfo) (*)

      禡wqJk module rBz覡CCϥΪ̺VJ@ӫA
      xcin K|Is禡Coɥ禡r䪺NqAݭn xcin 
      AAPɱNGǦ^ xcin iBzʧ@C䤤 conf P 
      inpinfo_t peҭzA keyinfo_t cwqpU:

typedef struct {
    KeySym keysym;                      /* X11 key code. */
    unsigned int keystate;              /* X11 key state/modifiers */
    char keystr[64];                    /* X11 key name (in ascii) */
    int keystr_len;                     /* key name length */
} keyinfo_t;


      禡Ǧ^ȥiHOpUN | (bitwise OR) զX:

      IMKEY_COMMIT:  ܥJkwզrAo xcin |N inpinfo->cch
		oӤrǵثe X app,  X app |NoӦrܦb
		WC

      IMKEY_ABSORB:  ܥJkNoӦrRRlFA xcin ݭn
		Lʧ@CΪkhbΩզr~C

      IMKEY_BELL:  ܥJknD xcin oXu͡v@nC

      IMKEY_SHIFTESC:  ܥثeϥΪ̤UFNqrAP٫UF
		shift AhJkNBzoӦrAӽ xcin Nr
		/bοJҲճBzC

      IMKEY_IGNORE:  ܳoӦr糧JkӨOSNqAJk
		BzoӦrA xcin NrѨLBzC


   13. int (*show_keystroke) (void *conf, simdinfo_t *simdinfo);

      禡ΨܬYӯSwrrXC xcin |ݭnIs禡A
      N禡һݪƸg simdinfo cǤJAHcwqpU:

typedef struct {
    int icid;                           /* ID of current Input Context */
    unsigned short xcin_wlen;           /* xcin window length */
    unsigned short guimode;             /* GUI mode flag */
    wch_t cch_publish;                  /* A published cch. */
    wch_t *s_keystroke;                 /* keystroke of cch_publish returned */
} simdinfo_t;

      䤤 cch_publish Y xcin Ʊ榹禡ܦrXrAөұo
      rXhg s_keystroke Ǧ^ xcin C

      Ъ`NA xcin ä@ s_keystroke wİϡAG禡ۦ@C
      @²檺kO禡ۦŧi@ static wİϡAMN s_keystroke
      VAҦp:

	  static wch_t my_keystroke[BUF_SIZE];
	  simdinfo->s_keystroke = my_keystroke;
	  .........




T.H.Hsieh
