Logo Search packages:      
Sourcecode: unicon version File versions  Download package

xl_intcode.c

/*
 *
 * UNICON - The Console Chinese & I18N
 * Copyright (c) 1999-2002
 *
 * This file is part of UNICON, a console Chinese & I18N
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * See the file COPYING directory of this archive
 * Author: see CREDITS
 */
/* GB2312:  A1A1-FEFE
 * GBK:         8140-FEFE
 * GB18030: 81308130-FE39FE39
 */

/*
 Compilation:
 Step1: gcc -g -Wall -I../../include -I. -c xl_intcode.c -o intcode.o
 Step2: gcc -g -shared intcode.o -o intcode.so
*/
/* Imm Standard Interfaces */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <ImmModule.h>
#include "xl_hzinput.h"

#define CODING_SINGLE_BYTE    0x01
#define CODING_DOUBLE_BYTES   0x02
#define CODING_FOUR_BYTES     0x04

hz_input_table *
IntCode_Init (void)
{
  hz_input_table *table;
  int i, index;

  table = malloc (sizeof (hz_input_table));
  if (table == NULL)
    {
      fprintf (stderr,
             "Out of memory in loading internel code input method\n");
      return NULL;
    }

  strcpy (table->magic_number, MAGIC_NUMBER);
  strcpy (table->ename, "HexCode");
  strcpy (table->cname, "롿");
  strcpy (table->selkey, "0123456789abcdef");

  table->last_full = 1;
  for (i = 0; i < 128; i++)
    {
      table->KeyMap[i] = 0;

      if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'f'))
      {
        if (i >= '0' && i <= '9')
          index = i - '0';
        else
          index = i - 'a' + 10;

        table->KeyMap[i] = index;
        table->KeyName[index] = toupper (i);
      }
    }
  return table;
}

int
ConfigureInputArea (HzInputTable_T * pHzInputTable, int nSelectionLen)
{
  pHzInputTable->MaxSelectLen = nSelectionLen;  //Rat: 48
  return 1;
}

void
ResetInput (HzInputTable_T * pHzInputTable)
{
  bzero (pHzInputTable->InpKey, sizeof (pHzInputTable->InpKey));
  bzero (pHzInputTable->seltab, sizeof (pHzInputTable->seltab));

  pHzInputTable->MultiPageMode = 0;
  pHzInputTable->NextPageIndex = 0;
  pHzInputTable->CurrentPageIndex = 0;
  pHzInputTable->CurSelNum = 0;
  pHzInputTable->InputCount = 0;
  pHzInputTable->InputMatch = 0;
  pHzInputTable->val1 = 0;
}

void
ClearSelection (HzInputTable_T * pHzInputTable)
{
  pHzInputTable->MultiPageMode = 0;
  pHzInputTable->NextPageIndex = 0;
  pHzInputTable->CurrentPageIndex = 0;
  pHzInputTable->CurSelNum = 0;
}

void
IntCode_FindMatchKey (HzInputTable_T * pHzInputTable)
{
  unsigned long Key;

  if (pHzInputTable->val1 == CODING_FOUR_BYTES) //GB18030 chars
    {
      Key = (pHzInputTable->InpKey[0] << 28)    //1st inputed key
      | (pHzInputTable->InpKey[1] << 24)  //2nd ik
      | (pHzInputTable->InpKey[2] << 20)  //3rd ik
      | (pHzInputTable->InpKey[3] << 16)  //4th ik
      | (pHzInputTable->InpKey[4] << 12)  //5th ik
      | (pHzInputTable->InpKey[5] << 8)   //6th ik
      | (pHzInputTable->InpKey[6] << 4);  //7th ik
    }
  else                        //GB2312/GBK chars
    {
      Key = (pHzInputTable->InpKey[0] << 12)    //1st ik
      | (pHzInputTable->InpKey[1] << 8)   //2nd ik
      | (pHzInputTable->InpKey[2] << 4);  //3rd ik
    }


  switch (pHzInputTable->InputCount)
    {
    case 3:
      if (pHzInputTable->val1 == CODING_DOUBLE_BYTES) //GB2312/GBK chars
      {
        pHzInputTable->StartKey = Key;
        pHzInputTable->EndKey = Key + 0x10;
      }
      else              //GB18030 chars
      pHzInputTable->StartKey = pHzInputTable->EndKey = 0;  //not end yet
      break;

    case 7:             //GB18030 chars
      pHzInputTable->StartKey = Key;      //xxxx xx30
      pHzInputTable->EndKey = Key + 0x0A; //xxxx xx39
      break;

    default:
      pHzInputTable->StartKey = pHzInputTable->EndKey = 0;
    }
}


void
IntCode_FillMatchChars (HzInputTable_T * pHzInputTable, int index)
{
  int MaxSel = 10, i = 0, k = 0, CurSelNum = 0;
  char temptab[16][16];

  for (i = 0; i < 16; i++)
    temptab[i][0] = '\0';

  if (pHzInputTable->InputCount < 2)      //Don't begin to search now
    return;

  if (pHzInputTable->InputCount == 7)     //GB18030 chars
    {
      while (CurSelNum < MaxSel && index < pHzInputTable->EndKey)
      {
        temptab[CurSelNum][0] = (char) ((index & 0xFF000000) >> 24);
        temptab[CurSelNum][1] = (char) ((index & 0x00FF0000) >> 16);
        temptab[CurSelNum][2] = (char) ((index & 0x0000FF00) >> 8);
        temptab[CurSelNum][3] = (char) ((index & 0x000000FF));
        temptab[CurSelNum][4] = '\0';
        CurSelNum++;
        index++;
      }

      for (k = 0; k < MaxSel; k++)
      {
        if (mbtowc (NULL, temptab[k], 4) > 0)
          strncpy (pHzInputTable->seltab[k], temptab[k], 4);
        else
          {
            pHzInputTable->seltab[k][0] = 0xa1;
            pHzInputTable->seltab[k][1] = 0xa1;
            pHzInputTable->seltab[k][2] = 0;
          }
      }
      pHzInputTable->MultiPageMode = 0;
    }
  else                        //GB2312/GBK
    {
      while (CurSelNum < MaxSel && index < pHzInputTable->EndKey)
      {
        temptab[CurSelNum][0] = index / 256;    //00-FF->0-256
        temptab[CurSelNum][1] = index % 256;
        temptab[CurSelNum][2] = '\0';
        CurSelNum++;
        index++;
      }

      for (k = 0; k < MaxSel; k++)
      {
        if (mbtowc (NULL, temptab[k], 2) > 0)
          strncpy (pHzInputTable->seltab[k], temptab[k], 2);
        else
          {
            pHzInputTable->seltab[k][0] = 0xa1;
            pHzInputTable->seltab[k][1] = 0xa1;
            pHzInputTable->seltab[k][2] = 0;
          }
      }
    }


  pHzInputTable->CurSelNum = CurSelNum;

  for (i = CurSelNum; i < 16; i++)
    pHzInputTable->seltab[i][0] = '\0';


  pHzInputTable->InputMatch = pHzInputTable->InputCount;

  if (index <= pHzInputTable->EndKey && CurSelNum == MaxSel && MaxSel == 10)
    {
      pHzInputTable->NextPageIndex = index;
      pHzInputTable->MultiPageMode = 1;
    }
  else if (pHzInputTable->MultiPageMode)
    {                   /* rotate selection */
      pHzInputTable->NextPageIndex = pHzInputTable->StartKey;
    }
  else
    pHzInputTable->MultiPageMode = 0;
}

int
Intcode_HZFilter (HzInputTable_T * pHzInputTable, unsigned char key,
              char *buff, int *len)
{
  int inkey = 0;
  char *pSelChar = NULL;
  int nSelIndex;

  switch (key)
    {
    case '\010':        /* BackSpace Ctrl+H */
    case '\177':        /* BackSpace */
      if (pHzInputTable->InputCount > 0)
      {
        pHzInputTable->InpKey[--pHzInputTable->InputCount] = 0;

        if (pHzInputTable->InputCount == 2)
          {
            pHzInputTable->val1 = 0;
            ClearSelection (pHzInputTable);
          }

        if (pHzInputTable->InputCount == 0)
          ResetInput (pHzInputTable);
        else if (pHzInputTable->InputCount > 2)
          {
            IntCode_FindMatchKey (pHzInputTable);     //searching
            pHzInputTable->MultiPageMode = 0;
            pHzInputTable->CurrentPageIndex = pHzInputTable->StartKey;
            IntCode_FillMatchChars (pHzInputTable, pHzInputTable->StartKey);
          }
      }
      else
      return 0;
      break;

    case '\033':        /* ESCAPE */
      if (pHzInputTable->InputCount > 0)
      ResetInput (pHzInputTable);
      else
      return 0;
      break;

    case '<':
    case '[':
    case '-':
    case ',':
      if (pHzInputTable->MultiPageMode)   //More than 10 results
      {
        if (pHzInputTable->CurrentPageIndex > pHzInputTable->StartKey)
          {
            pHzInputTable->CurrentPageIndex =
            pHzInputTable->CurrentPageIndex - 10;
          }
        else
          {
            pHzInputTable->CurrentPageIndex = pHzInputTable->StartKey;
          }

        IntCode_FillMatchChars (pHzInputTable,
                          pHzInputTable->CurrentPageIndex);
      }
      else              //Less than 10 results
      return 0;
      break;

    case '>':
    case ']':
    case '.':
    case '=':
      if (pHzInputTable->MultiPageMode)
      {
        pHzInputTable->CurrentPageIndex = pHzInputTable->NextPageIndex;

        IntCode_FillMatchChars (pHzInputTable,
                          pHzInputTable->CurrentPageIndex);
      }
      else
      return 0;
      break;

    case ' ':
      if (pHzInputTable->CurSelNum == 0)
      return 0;

      if (pHzInputTable->seltab[0][0])    //available
      {
        strcpy (buff, pHzInputTable->seltab[0]);
        *len = strlen (buff);
        ResetInput (pHzInputTable);
        return 2;
      }
      break;

    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
    case 'a':
    case 'b':
    case 'c':
    case 'd':
    case 'e':
    case 'f':
      inkey = pHzInputTable->cur_table->KeyMap[key];
      pSelChar = strchr (pHzInputTable->cur_table->selkey, key);
      nSelIndex = pSelChar - pHzInputTable->cur_table->selkey;

      if (pSelChar
        && pHzInputTable->CurSelNum > 0
        && pHzInputTable->seltab[nSelIndex][0])
      {
        strcpy (buff, pHzInputTable->seltab[nSelIndex]);
        *len = strlen (buff);
        ResetInput (pHzInputTable);
        return 2;
      }

      switch (pHzInputTable->InputCount % 4)    //0/4 keys
      {
      case 0:           /* 8-F */
        if (inkey < 8)  //invalid 1st hexcode of GB2312/GBK/GB18030 Set
          {
            return 0;
          }
        else
          {
            pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey;
          }
        break;

      case 1:           /* 0-F *///1/5 keys
        if (((pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 8) && (inkey == 0)) || ((pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 15) && (inkey == 15))) //0x80 or 0xFF is invalid
          {
            return 0;
          }
        else
          {
            pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey;
          }
        break;

      case 2:           /* 3-F *///2/6 keys
        if (inkey < 3)
          {
            return 0;
          }
        else if (inkey == 3)
          {
            pHzInputTable->val1 = CODING_FOUR_BYTES;
            ClearSelection (pHzInputTable);
            pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey;

            if (pHzInputTable->InputCount == 7) //4bytes char
            {
              IntCode_FindMatchKey (pHzInputTable);

              pHzInputTable->MultiPageMode = 0;
              pHzInputTable->CurrentPageIndex = pHzInputTable->StartKey;

              IntCode_FillMatchChars (pHzInputTable,
                                pHzInputTable->StartKey);
            }
          }
        else if (pHzInputTable->InputCount == 2)
          {
            pHzInputTable->val1 = CODING_DOUBLE_BYTES;
            pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey;
            IntCode_FindMatchKey (pHzInputTable);
            pHzInputTable->MultiPageMode = 0;
            pHzInputTable->CurrentPageIndex = pHzInputTable->StartKey;
            IntCode_FillMatchChars (pHzInputTable, pHzInputTable->StartKey);
          }
        else
          {
            return 0;
          }
        break;
      case 3:           /* output char *///3/7 keys
        /* A1A1-FEFE */
        if (((pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 7)
             && (inkey == 15))
            || ((pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 15)
              && (inkey == 15))
            || ((pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 3)
              && (inkey > 9)))
          //0x7F or 0xFF or 3A-3F is invalid
          {
            return 0;
          }
        else
          {
            if (pHzInputTable->val1 & CODING_DOUBLE_BYTES)
            {
              pHzInputTable->seltab[0][0] =
                (pHzInputTable->InpKey[0] << 4) | pHzInputTable->
                InpKey[1];

              pHzInputTable->seltab[0][1] =
                (pHzInputTable->InpKey[2] << 4) | inkey;

              pHzInputTable->seltab[0][2] = '\0';

              strcpy (buff, pHzInputTable->seltab[0]);
              *len = strlen (buff);
              ResetInput (pHzInputTable);
              return 2;

            }

            if ((pHzInputTable->val1 & CODING_FOUR_BYTES) && (pHzInputTable->InputCount == 7))  //only 7 keys
            {
              pHzInputTable->seltab[0][0] =
                (pHzInputTable->InpKey[0] << 4) | pHzInputTable->
                InpKey[1];

              pHzInputTable->seltab[0][1] =
                (pHzInputTable->InpKey[2] << 4) | pHzInputTable->
                InpKey[3];

              pHzInputTable->seltab[0][2] =
                (pHzInputTable->InpKey[4] << 4) | pHzInputTable->
                InpKey[5];

              pHzInputTable->seltab[0][3] =
                (pHzInputTable->InpKey[6] << 4) | inkey;

              pHzInputTable->seltab[0][4] = '\0';

              strcpy (buff, pHzInputTable->seltab[0]);
              *len = strlen (buff);

              ResetInput (pHzInputTable);

              return 2;
            }

            pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey;
          }
        break;
      }
    default:
      break;
    }                   /* switch */
  return 1;
}

int
GetSelectDisplay (HzInputTable_T * pHzInputTable, char *strBuf, int nBufLen)
{
  int i, pos = 0, len;

  if (pHzInputTable->MultiPageMode && pHzInputTable->CurrentPageIndex != pHzInputTable->StartKey)     /* not first page */
    {
      strcpy (strBuf + pos, "< ");
      pos += 2;
    }

  for (i = 0; i < pHzInputTable->CurSelNum; i++)
    {
      if (!pHzInputTable->seltab[i][0])   //from 0-MaxSel
      break;

      len = strlen (pHzInputTable->seltab[i]);
      if (pos + len + 3 > nBufLen)
      break;

      sprintf (strBuf + pos, "%d%s ", i, pHzInputTable->seltab[i]);
      pos += len + 2;

    }

  if (pHzInputTable->MultiPageMode && pHzInputTable->NextPageIndex != pHzInputTable->StartKey)  /* not last page */
    {
      strcpy (strBuf + pos, " >");
      pos += 2;
    }

  strBuf[pos] = '\0';
  return pHzInputTable->CurSelNum ? 1 : 0;
}

int
GetInputDisplay (HzInputTable_T * pHzInputTable, char *buf)
{
  int i = 0;
  buf[0] = '\0';

  for (i = 0; i < pHzInputTable->InputCount; i++)
    sprintf (buf + i, "%c",
           pHzInputTable->cur_table->KeyName[pHzInputTable->InpKey[i]]);

  buf[pHzInputTable->InputCount] = '\0';

  return pHzInputTable->InputCount ? 1 : 0;
}


/* ********************** Now the interface functions *********************** */
static IMM_CLIENT *
IMM_open (char *szFileName, long type)
{
  HzInputTable_T *pHzInputTable_T;
  IMM_CLIENT *pIMM_CLIENT;
  hz_input_table *phz_input_table;

  phz_input_table = IntCode_Init ();
  if (phz_input_table == NULL)
    {
      fprintf (stderr, "Error in malloc for phz_input_table.\n");
      return NULL;
    }

  pHzInputTable_T = (HzInputTable_T *) malloc (sizeof (HzInputTable_T));
  if (pHzInputTable_T == NULL)
    {
      free (phz_input_table);
      fprintf (stderr, "Error in malloc for pHzInputTable.\n");
      return NULL;
    }

  pIMM_CLIENT = (IMM_CLIENT *) malloc (sizeof (IMM_CLIENT));
  if (pIMM_CLIENT == NULL)
    {
      free (pHzInputTable_T);
      free (phz_input_table);
      fprintf (stderr, "Error in malloc for pIMM_CLIENT.\n");
      return NULL;
    };

  ResetInput (pHzInputTable_T);
  ConfigureInputArea (pHzInputTable_T, 48);     //48 is not good
  pIMM_CLIENT->pImmClientData = (void *) pHzInputTable_T;
  pHzInputTable_T->cur_table = phz_input_table;

  return pIMM_CLIENT;
}

static int
IMM_save (IMM_CLIENT * p, char *szFileName)
{
  return 1;
}

static int
IMM_close (IMM_CLIENT * p)
{
  HzInputTable_T *pClient = (HzInputTable_T *) p->pImmClientData;
  free (pClient->cur_table);
  free (p->pImmClientData);
  free (p);
  return 1;
}

/* Indepent Modules support */
static int
IMM_KeyFilter (IMM_CLIENT * p, u_char key, char *buf, int *len)
{
  buf[0] = '\0';
  *len = 0;
  return Intcode_HZFilter ((HzInputTable_T *) p->pImmClientData, key, buf,
                     len);
}

/* Input Area Configuration & Operation */
static int
IMM_ConfigInputArea (IMM_CLIENT * p, int SelectionLen)
{
  return ConfigureInputArea ((HzInputTable_T *) p->pImmClientData,
                       SelectionLen);
}

static int
IMM_GetInputDisplay (IMM_CLIENT * p, char *buf, long buflen)
{
  return GetInputDisplay ((HzInputTable_T *) p->pImmClientData, buf);
}

static int
IMM_GetSelectDisplay (IMM_CLIENT * p, char *buf, long buflen)
{
  return GetSelectDisplay ((HzInputTable_T *) p->pImmClientData, buf, buflen);
}

int
IMM_ResetInput (IMM_CLIENT * p)
{
  ResetInput ((HzInputTable_T *) p->pImmClientData);
  return 1;
}

#ifdef  __cplusplus
extern "C"
#endif
struct ImmOperation ImmOp_Ptr = {
  "",
  "CJKVInput Version 3.0",
  "Author:Dianzhi Wang",      /* Codes based on HappyConsole from Legend. */
  IMM_CCE | IMM_LC_GB18030 << 24,
  IMM_open,
  IMM_save,
  IMM_close,

  /* Indepent Modules support */
  IMM_KeyFilter,
  IMM_ResetInput,

  /* Input Area Configuration & Operation */
  IMM_ConfigInputArea,
  IMM_GetInputDisplay,
  IMM_GetSelectDisplay,
  NULL,                       //IMM_pGetItem,
  NULL,                       //IMM_AddPhrase,
  NULL,                       //IMM_ModifyPhraseItem,
  NULL,                       //IMM_Flush,
};

//Test part
#ifdef      __CCE_HZINPUT_DEBUG__
/*
Compilation:
  gcc -g -I../../include -I. -D__CCE_HZINPUT_DEBUG__ GB18030_intcode.c -o intcode_test
Run:
  ./intcode_test
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <xl_hzinput.h>
#include <ImmModule.h>

extern struct ImmOperation ImmOp_Ptr;

int
test (IMM_CLIENT * pImm, char *inbuf, char *type)
{
  int i, j, len;
  long n;
  char buf1[64];

  printf ("Charset: %s\n", type);
  for (i = 0; i < strlen (inbuf); i++)
    {
      char buf[256];
      n = ImmOp_Ptr.KeyFilter (pImm, inbuf[i], buf1, &len);
      ImmOp_Ptr.GetInputDisplay (pImm, buf, sizeof (buf)),
      printf ("Input::%s\n", buf);
      ImmOp_Ptr.GetSelectDisplay (pImm, buf, sizeof (buf));
      printf ("Selection::%s\n", buf);

      if (n == 2)
      printf ("you select::%s\n", buf1);
      printf ("\n");
    }
}

int
main ()
{
  IMM_CLIENT *pImm;
  char *szTest1 = "8140 ";
  char *szTest2 = "8139ef39 ";

  pImm = ImmOp_Ptr.open (NULL, 0);
  pImm->m.szPhrase = pImm->buf;

  printf ("\n");
  test (pImm, szTest1, "GBK");
  test (pImm, szTest2, "GB18030");
  printf ("\n");
  ImmOp_Ptr.close (pImm);
  return 1;
}
#endif

Generated by  Doxygen 1.6.0   Back to index