// -*- mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
/* Unikey Vietnamese Input Method
* Copyright (C) 2000-2005 Pham Kim Long
* Contact:
* unikey@gmail.com
* UniKey project: http://unikey.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor
* Boston, MA 02110-1301, USA.
*/
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
#include <ctype.h>
#include "usrkeymap.h"
int getLabelIndex(int action);
void initKeyMap(int keyMap[256]);
#define OPT_COMMENT_CHAR ';'
struct UkEventLabelPair
{
char label[32];
int ev;
};
UkEventLabelPair UkEvLabelList[] = {
{"Tone0", vneTone0},
{"Tone1", vneTone1},
{"Tone2", vneTone2},
{"Tone3", vneTone3},
{"Tone4", vneTone4},
{"Tone5", vneTone5},
{"Roof-All", vneRoofAll},
{"Roof-A", vneRoof_a},
{"Roof-E", vneRoof_e},
{"Roof-O", vneRoof_o},
{"Hook-Bowl", vneHookAll},
{"Hook-UO", vneHook_uo},
{"Hook-U", vneHook_u},
{"Hook-O", vneHook_o},
{"Bowl", vneBowl},
{"D-Mark", vneDd},
{"Telex-W", vne_telex_w},
{"Escape", vneEscChar},
{"DD", vneCount + vnl_DD},
{"dd", vneCount + vnl_dd},
{"A^", vneCount + vnl_Ar},
{"a^", vneCount + vnl_ar},
{"A(", vneCount + vnl_Ab},
{"a(", vneCount + vnl_ab},
{"E^", vneCount + vnl_Er},
{"e^", vneCount + vnl_er},
{"O^", vneCount + vnl_Or},
{"o^", vneCount + vnl_or},
{"O+", vneCount + vnl_Oh},
{"o+", vneCount + vnl_oh},
{"U+", vneCount + vnl_Uh},
{"u+", vneCount + vnl_uh}
};
const int UkEvLabelCount = sizeof(UkEvLabelList)/sizeof(UkEventLabelPair);
//--------------------------------------------------
static int parseNameValue(char *line, char **name, char **value)
{
char *p, *mark;
char ch;
if (line == 0)
return 0;
// get rid of comment
p = strchr(line, OPT_COMMENT_CHAR);
if (p)
*p = 0;
//get option name
for (p=line; *p == ' '; p++);
if (*p == 0)
return 0;
*name = p;
mark = p; //mark the last non-space character
p++;
while ((ch=*p) != '=' && ch!=0) {
if (ch != ' ')
mark = p;
p++;
}
if (ch == 0)
return 0;
*(mark+1) = 0; //terminate name with a null character
//get option value
p++;
while (*p == ' ') p++;
if (*p == 0)
return 0;
*value = p;
mark = p;
while (*p) { //strip trailing spaces
if (*p != ' ')
mark = p;
p++;
}
*++mark = 0;
return 1;
}
//-----------------------------------------------------
DllExport int UkLoadKeyMap(const char *fileName, int keyMap[256])
{
int i, mapCount;
UkKeyMapPair orderMap[256];
if (!UkLoadKeyOrderMap(fileName, orderMap, &mapCount))
return 0;
initKeyMap(keyMap);
for (i=0; i < mapCount; i++) {
keyMap[orderMap[i].key] = orderMap[i].action;
if (orderMap[i].action < vneCount) {
keyMap[tolower(orderMap[i].key)] = orderMap[i].action;
}
}
return 1;
}
//------------------------------------------------------------------
DllExport int UkLoadKeyOrderMap(const char *fileName, UkKeyMapPair *pMap, int *pMapCount)
{
FILE *f;
char *buf;
char *name, *value;
size_t len;
int i, bufSize, lineCount;
unsigned char c;
int mapCount;
int keyMap[256];
f = fopen(fileName, "r");
if (f == 0) {
cerr << "Failed to open file: " << fileName << endl;
return 0;
}
initKeyMap(keyMap);
bufSize = 256;
buf = new char[bufSize];
lineCount = 0;
mapCount = 0;
while (!feof(f)) {
if (fgets((char *)buf, bufSize, f) == 0)
break;
lineCount++;
len = strlen(buf);
if (len == 0)
break;
if (buf[len-1] == '\n')
buf[len-1] = 0;
if (parseNameValue(buf, (char **)&name, (char **)&value)) {
if (strlen(name) == 1) {
for (i=0; i < UkEvLabelCount; i++) {
if (strcmp(UkEvLabelList[i].label, value) == 0) {
c = (unsigned char)name[0];
if (keyMap[c] != vneNormal) {
//already assigned, don't accept this map
break;
}
//cout << "key: " << c << " value: " << UkEvLabelList[i].ev << endl; //DEBUG
keyMap[c] = UkEvLabelList[i].ev;
pMap[mapCount].action = UkEvLabelList[i].ev;
if (keyMap[c] < vneCount) {
pMap[mapCount].key = toupper(c);
keyMap[toupper(c)] = UkEvLabelList[i].ev;
}
else {
pMap[mapCount].key = c;
}
mapCount++;
break;
}
}
if (i == UkEvLabelCount) {
cerr << "Error in user key layout, line " << lineCount << ": command not found" << endl;
}
}
else {
cerr << "Error in user key layout, line " << lineCount
<< ": key name is not a single character" << endl;
}
}
}
delete [] buf;
fclose(f);
*pMapCount = mapCount;
return 1;
}
//-------------------------------------------
void initKeyMap(int keyMap[256])
{
unsigned int c;
for (c=0; c<256; c++)
keyMap[c] = vneNormal;
}
const char *UkKeyMapHeader =
"; This is UniKey user-defined key mapping file, generated from UniKey (Windows)\n\n";
DllExport int UkStoreKeyOrderMap(const char *fileName, UkKeyMapPair *pMap, int mapCount)
{
FILE *f;
int i;
int labelIndex;
char line[128];
f = fopen(fileName, "wt");
if (f == 0) {
cerr << "Failed to open file: " << fileName << endl;
return 0;
}
fputs(UkKeyMapHeader, f);
for (i=0; i < mapCount; i++) {
labelIndex = getLabelIndex(pMap[i].action);
if (labelIndex != -1) {
sprintf(line, "%c = %s\n", pMap[i].key, UkEvLabelList[labelIndex].label);
fputs(line, f);
}
}
fclose(f);
return 1;
}
int getLabelIndex(int event)
{
int i;
for (i = 0; i < UkEvLabelCount; i++) {
if (UkEvLabelList[i].ev == event)
return i;
}
return -1;
}