michael@0: /******* BEGIN LICENSE BLOCK ******* michael@0: * Version: MPL 1.1/GPL 2.0/LGPL 2.1 michael@0: * michael@0: * The contents of this file are subject to the Mozilla Public License Version michael@0: * 1.1 (the "License"); you may not use this file except in compliance with michael@0: * the License. You may obtain a copy of the License at michael@0: * http://www.mozilla.org/MPL/ michael@0: * michael@0: * Software distributed under the License is distributed on an "AS IS" basis, michael@0: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License michael@0: * for the specific language governing rights and limitations under the michael@0: * License. michael@0: * michael@0: * The Initial Developers of the Original Code are Kevin Hendricks (MySpell) michael@0: * and László Németh (Hunspell). Portions created by the Initial Developers michael@0: * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved. michael@0: * michael@0: * Contributor(s): László Németh (nemethl@gyorsposta.hu) michael@0: * Caolan McNamara (caolanm@redhat.com) michael@0: * michael@0: * Alternatively, the contents of this file may be used under the terms of michael@0: * either the GNU General Public License Version 2 or later (the "GPL"), or michael@0: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), michael@0: * in which case the provisions of the GPL or the LGPL are applicable instead michael@0: * of those above. If you wish to allow use of your version of this file only michael@0: * under the terms of either the GPL or the LGPL, and not to allow others to michael@0: * use your version of this file under the terms of the MPL, indicate your michael@0: * decision by deleting the provisions above and replace them with the notice michael@0: * and other provisions required by the GPL or the LGPL. If you do not delete michael@0: * the provisions above, a recipient may use your version of this file under michael@0: * the terms of any one of the MPL, the GPL or the LGPL. michael@0: * michael@0: ******* END LICENSE BLOCK *******/ michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include "dictmgr.hxx" michael@0: michael@0: DictMgr::DictMgr(const char * dictpath, const char * etype) : numdict(0) michael@0: { michael@0: // load list of etype entries michael@0: pdentry = (dictentry *)malloc(MAXDICTIONARIES*sizeof(struct dictentry)); michael@0: if (pdentry) { michael@0: if (parse_file(dictpath, etype)) { michael@0: numdict = 0; michael@0: // no dictionary.lst found is okay michael@0: } michael@0: } michael@0: } michael@0: michael@0: michael@0: DictMgr::~DictMgr() michael@0: { michael@0: dictentry * pdict = NULL; michael@0: if (pdentry) { michael@0: pdict = pdentry; michael@0: for (int i=0;ilang) { michael@0: free(pdict->lang); michael@0: pdict->lang = NULL; michael@0: } michael@0: if (pdict->region) { michael@0: free(pdict->region); michael@0: pdict->region=NULL; michael@0: } michael@0: if (pdict->filename) { michael@0: free(pdict->filename); michael@0: pdict->filename = NULL; michael@0: } michael@0: pdict++; michael@0: } michael@0: free(pdentry); michael@0: pdentry = NULL; michael@0: pdict = NULL; michael@0: } michael@0: numdict = 0; michael@0: } michael@0: michael@0: michael@0: // read in list of etype entries and build up structure to describe them michael@0: int DictMgr::parse_file(const char * dictpath, const char * etype) michael@0: { michael@0: michael@0: int i; michael@0: char line[MAXDICTENTRYLEN+1]; michael@0: dictentry * pdict = pdentry; michael@0: michael@0: // open the dictionary list file michael@0: FILE * dictlst; michael@0: dictlst = fopen(dictpath,"r"); michael@0: if (!dictlst) { michael@0: return 1; michael@0: } michael@0: michael@0: // step one is to parse the dictionary list building up the michael@0: // descriptive structures michael@0: michael@0: // read in each line ignoring any that dont start with etype michael@0: while (fgets(line,MAXDICTENTRYLEN,dictlst)) { michael@0: mychomp(line); michael@0: michael@0: /* parse in a dictionary entry */ michael@0: if (strncmp(line,etype,4) == 0) { michael@0: if (numdict < MAXDICTIONARIES) { michael@0: char * tp = line; michael@0: char * piece; michael@0: i = 0; michael@0: while ((piece=mystrsep(&tp,' '))) { michael@0: if (*piece != '\0') { michael@0: switch(i) { michael@0: case 0: break; michael@0: case 1: pdict->lang = mystrdup(piece); break; michael@0: case 2: if (strcmp (piece, "ANY") == 0) michael@0: pdict->region = mystrdup(""); michael@0: else michael@0: pdict->region = mystrdup(piece); michael@0: break; michael@0: case 3: pdict->filename = mystrdup(piece); break; michael@0: default: break; michael@0: } michael@0: i++; michael@0: } michael@0: free(piece); michael@0: } michael@0: if (i == 4) { michael@0: numdict++; michael@0: pdict++; michael@0: } else { michael@0: switch (i) { michael@0: case 3: michael@0: free(pdict->region); michael@0: pdict->region=NULL; michael@0: case 2: //deliberate fallthrough michael@0: free(pdict->lang); michael@0: pdict->lang=NULL; michael@0: default: michael@0: break; michael@0: } michael@0: fprintf(stderr,"dictionary list corruption in line \"%s\"\n",line); michael@0: fflush(stderr); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: fclose(dictlst); michael@0: return 0; michael@0: } michael@0: michael@0: // return text encoding of dictionary michael@0: int DictMgr::get_list(dictentry ** ppentry) michael@0: { michael@0: *ppentry = pdentry; michael@0: return numdict; michael@0: } michael@0: michael@0: michael@0: michael@0: // strip strings into token based on single char delimiter michael@0: // acts like strsep() but only uses a delim char and not michael@0: // a delim string michael@0: michael@0: char * DictMgr::mystrsep(char ** stringp, const char delim) michael@0: { michael@0: char * rv = NULL; michael@0: char * mp = *stringp; michael@0: size_t n = strlen(mp); michael@0: if (n > 0) { michael@0: char * dp = (char *)memchr(mp,(int)((unsigned char)delim),n); michael@0: if (dp) { michael@0: *stringp = dp+1; michael@0: size_t nc = dp - mp; michael@0: rv = (char *) malloc(nc+1); michael@0: if (rv) { michael@0: memcpy(rv,mp,nc); michael@0: *(rv+nc) = '\0'; michael@0: } michael@0: } else { michael@0: rv = (char *) malloc(n+1); michael@0: if (rv) { michael@0: memcpy(rv, mp, n); michael@0: *(rv+n) = '\0'; michael@0: *stringp = mp + n; michael@0: } michael@0: } michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: michael@0: // replaces strdup with ansi version michael@0: char * DictMgr::mystrdup(const char * s) michael@0: { michael@0: char * d = NULL; michael@0: if (s) { michael@0: int sl = strlen(s)+1; michael@0: d = (char *) malloc(sl); michael@0: if (d) memcpy(d,s,sl); michael@0: } michael@0: return d; michael@0: } michael@0: michael@0: michael@0: // remove cross-platform text line end characters michael@0: void DictMgr:: mychomp(char * s) michael@0: { michael@0: int k = strlen(s); michael@0: if ((k > 0) && ((*(s+k-1)=='\r') || (*(s+k-1)=='\n'))) *(s+k-1) = '\0'; michael@0: if ((k > 1) && (*(s+k-2) == '\r')) *(s+k-2) = '\0'; michael@0: } michael@0: