Package: zhcon
Version: 1:0.2.6-5.1
Severity: normal
Tags: patch

--- Please enter the report below this line. ---
this bug and patch is forwarded from 
http://www.newsmth.net/bbscon.php?bid=69&id=219962, the origin author of this 
bug report and patch is [EMAIL PROTECTED]

zhcon will crash when use input method under amd64, replace the corresponding 
files with the attachment can fix this bug. (not verifed yet)

--- System information. ---
Architecture: amd64
Kernel:       Linux 2.6.26-1-amd64

Debian Release: lenny/sid
  500 unstable        127.0.0.1 

--- Package information. ---
Depends                   (Version) | Installed
===================================-+-====================
debconf                             | 1.5.21
libc6                    (>= 2.7-1) | 2.7-10
libgcc1             (>= 1:4.1.1-21) | 1:4.3.2-1
libggi2                (>= 1:2.2.1) | 1:2.2.2-2
libncurses5     (>= 5.6+20071006-3) | 5.6+20080419-2
libpth20               (>= 2.0.7-8) | 2.0.7-10
libstdc++6             (>= 4.2.1-4) | 4.3.2-1
unicon-imc2                         | 3.0.4-12.1
// vi:ts=4:shiftwidth=4:expandtab
/***************************************************************************
                          winime.h  -  description
                             -------------------
    begin                : Wed Apr 4 2001
    copyright            : (C) 2001 by ejoy
    email                : [EMAIL PROTECTED]
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef WINIME_H
#define WINIME_H

/**
 [EMAIL PROTECTED] ejoy
 */
using namespace std;

#include <string>

class Candilist;
struct WinImeHead {
    char mName[12];
    int mMaxCodes;
    char mCodeSet[47];
    char mWildChar;
};

class WinIme {
    public:
        WinIme(const char* arg);
        ~WinIme();

        bool IsWildChar(char c) const {
            return c == mHead.mWildChar;
        }
        string GetName();
        bool InCodeSet(char c) const;
        int Search(string& s, int start);
        void SetCandilist(Candilist* p,unsigned len = 1000) {
            mpList = p;
            mCandilistBufLen = len;
        }
        void Reset();
        void SetGBKOut(bool v) {
            mGBKOut = v;
        }
        bool GetGBKOut() {
            return mGBKOut;
        }
        int mNum;        //number of chars processed in code queue
    private:

        bool IsHzCode1(char c) {
            return (c > 0x80 && c < 0xFF);
        }
        bool IsGB2312_1(char c) const {
            return c >= 0xA1 && c <= 0xF7;
        }
        bool IsGB2312_2(char c) const {
            return c >= 0xA1 && c <= 0xFE;
        }

        void AddCandilist(char*& p,unsigned& buflen);
        void SkipNext(char*& rp);
        int MatchWord(char* p, int len, int offset);
        bool IsGB2312(char* p);
        int Index(char c);
        int Search(int start);
        int Search(char c);

        char mInput[12 + 1];
        bool mGBKOut;
        Candilist* mpList;
        char * mpOffset[12];
        int mFd;
        char* mpBuf;
        int *mpIndex1;
        int *mpIndex2;
        char* mpText;
        char* mpCur;                  //current search position
        unsigned int mBufSize;
        unsigned int mCandilistBufLen;
        WinImeHead mHead;
};
#endif
// vi:ts=4:shiftwidth=4:expandtab
/***************************************************************************
                          winime.cpp  -  description
                             -------------------
    begin                : Wed Apr 4 2001
    copyright            : (C) 2001 by ejoy
    email                : [EMAIL PROTECTED]
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <cassert>
#include <functional>
#include <algorithm>
#include <stdexcept>

#include "candilist.h"
#include "winime.h"

WinIme::WinIme(const char *arg)
:mNum(0),
mGBKOut(false),
mpList(NULL),
mpCur((char *) 0xffffffff),
mCandilistBufLen(0)
{
    //     mList.mCount = 0;
    mFd = open(arg, O_RDONLY);
    if (mFd == -1)
        throw runtime_error("Can not open winime mb file!");

    struct stat st;
    if (fstat(mFd, &st) == -1)
        throw (runtime_error("can not get gbfont size!"));

    mBufSize = st.st_size;
    mpBuf = (char *) mmap(0, mBufSize, PROT_READ, MAP_SHARED, mFd, 0);
    if (mpBuf == MAP_FAILED)
        throw (runtime_error("mmap failed!"));

    fill_n(mInput, 13, '\0');
    fill_n(mpOffset, 12, (char *) 0xffffffff);

    memcpy(&mHead, mpBuf, sizeof(mHead));
    int len = strlen(mHead.mCodeSet);
    mpIndex1 = (int *) (mpBuf + sizeof(mHead));
    mpIndex2 = (int *) (mpBuf + sizeof(mHead) + len * sizeof(int));
    mpText = mpBuf + sizeof(mHead) + len * sizeof(int) +
                len * len * sizeof(int);
}

WinIme::~WinIme() {
    munmap(mpBuf, mBufSize);
    close(mFd);
}

bool WinIme::InCodeSet(char c) const {
    for (const char *p = mHead.mCodeSet; *p; p++)
        if (*p == c)
            return true;
    return false;
}
//add a word to candilist then push rp forward
void WinIme::AddCandilist(char *&rp,unsigned int& buflen) {
    assert(mpList->mCount < 10);
    assert(!IsHzCode1(*rp)); //*rp is last matched latter

    string & s = mpList->mList[mpList->mCount].mText;
    char &c = mpList->mList[mpList->mCount].mKey;
    mpList->mCount++;
    s = "";
    rp++;
    if (!IsHzCode1(*rp))
        c = *rp;
    else
        c = '\0';
    //skip non-hzcode
    while (!IsHzCode1(*rp))
        rp++;
    while (IsHzCode1(*rp)) {
        s += *rp++;
        s += *rp++;
    }
    buflen += s.size();
    buflen += (c != '\0' ? 4: 3);
}

string WinIme::GetName() {
    return mHead.mName;
}

void WinIme::Reset() {
    mNum = 0;
    fill_n(mInput, 13, '\0');
    //     mpList->mCount = 0;
    fill_n(mpOffset, 12, (char *) 0xffffffff);	  //?
}

//push rp to next word
void WinIme::SkipNext(char *&rp) {
    while (!IsHzCode1(*rp))
        rp++;
    while (IsHzCode1(*rp))
        rp += 2;
}

//skip offset words from p
//then Match next (at most)10 words and update mList.mHaveNext
//the word's length is num
int WinIme::MatchWord(char *p, int len, int offset) {
    int count = 0;
    int n;
    char *q;
    char *t;
    size_t buflen = 0;
    while (*p) {
        n = len - 1;
        q = mInput;
        t = p;
        while (n && !IsHzCode1(*t) && (*t == *q || *q == mHead.mWildChar)) {
            n--;
            t++;
            q++;
        }
        if (n == 0) {
            //now compare the last latter
            if (!IsHzCode1(*t) && (*t == *q || *q == mHead.mWildChar)) {
                if (!mGBKOut)
                    if (!IsGB2312(t)) {
                        SkipNext(t);
                        goto out;
                    }
                if (offset-- > 0) {
                    SkipNext(t);
                    goto out;
                }
                if (++count == 1) {
                    //success! now clear list.
                    //DO NOT touch mplist->mHavePrev,it is maintained
                    //in InputServer
                    mpList->mCount = 0;
        		    mpList->mHaveNext = false;
                    if (mpOffset[len - 1] == (char *) 0xffffffff)
                        mpOffset[len - 1] = p;
                    mpCur = p;
                }
                assert(len == mNum);
                if (count > 10 || buflen > mCandilistBufLen) {
        			mpList->mHaveNext = true;
		        	count--;
                    break;
		        }
                AddCandilist(t,(unsigned int&)buflen);
            } //search next word
            else {
                if (len == 1)   //special for first char
                    break;
                SkipNext(t);
            }
    out:
            p = t;
        } else  //not found!
            break;
    }//while
    return count;
}

//test the next word
bool WinIme::IsGB2312(char *p) {
    while (!IsHzCode1(*p))  //skip code
        p++;
    while (IsGB2312_1(*p) && IsGB2312_2(*(p + 1)))
        p += 2;
    return !IsHzCode1(*p);
}

//return c's index in codeset
int WinIme::Index(char c) {
    char *p;
    int len = strlen(mHead.mCodeSet);
    p = find(mHead.mCodeSet, mHead.mCodeSet + len, c);
    assert(p - mHead.mCodeSet < len);
    return p - mHead.mCodeSet;
}

int WinIme::Search(string & s, int start) {
    if (s.size() == 0 || s.size() > 12)
        return 0;
    int count;
    int i;
    int size = s.size();
    assert(mNum == (signed) strlen(mInput));
    //wildchar should not occur in 1st index
    assert(!(size == 1 && s[0] == mHead.mWildChar));
    for (i = 0; i < size; i++)
        if (s[i] != mInput[i])
            break;
    if (!(i == size && i == mNum)) {
        //not exact match
        mNum = i;
        fill(&mInput[i], mInput + 12, '\0');
        fill(&mpOffset[i], mpOffset + 12, (char *) 0xffffffff);
        //search rest chars
        while (i < size && (count = Search(s[i])))
            i++;
        if (i < size)
            return 0;
    }
    //all chars have been searched,now search for words needed
    assert(mNum == size);
    return Search(start);
}

//prev mNum chars have been searched
//now start a new search on c
//return count of words found
int WinIme::Search(char c) {
    char *p = NULL;
    bool found = true;
    mInput[mNum] = c;



    if (mNum == 0) {
        //1st level index
        //maybe prevent wildchar in 1st index is a good ideal
        //to input '?' faster
        if (c == mHead.mWildChar) {
            assert(!"should not find wildchar in 1st index.");
            //            char** t;
            //            int l = strlen(mHead.mCodeSet);
            //            t = find_if(mpIndex1,mpIndex1 + l,bind2nd(not_equal_to<char*>(), (char*)0xffffffff));
            //            if (t == mpIndex1 + l)
            //                p = (char*)0xffffffff;
            //            else
            //                p = *t;
        }
        else
	{
            p = (char *)mpIndex1[Index(c)];
	}

        if (p == (char *) 0xffffffff)
            found = false;
        p = (unsigned long) p + mpText;
    } //2nd level index
    else if (mNum == 1) {
        int l = strlen(mHead.mCodeSet);
        if (c == mHead.mWildChar) {
            char **t;
            t =
                find_if((char **)(mpIndex2 + Index(mInput[0]) * l),
                        (char **)(mpIndex2 + (Index(mInput[0]) + 1) * l),
                        bind2nd(not_equal_to < char *>(),
                                (char *) 0xffffffff));
            if (t == ((char **)mpIndex2) + (Index(mInput[0]) + 1) * l)
	    {
                p = (char *) 0xffffffff;
	    }
            else
                p = *t;
        } else
	{
		int dd =  Index(mInput[0]) * l + Index(c);
            p = (char *)(mpIndex2[Index(mInput[0]) * l + Index(c)]);
	}

        if (p == (char *) 0xffffffff)
            found = false;
        p = (unsigned long) p + mpText;
    } else if (mNum < mHead.mMaxCodes) {
        p = mpOffset[mNum - 1];
        if (p == (char *) 0xffffffff)
            found = false;
    } else
        found = false;

    if (!found) {
        mInput[mNum] = '\0';
        return 0;
    }
    //p is a valid offset now

    mNum++;
    int count = MatchWord(p, mNum, 0);
    if (count == 0) { //reject ch
        mNum--;
        mInput[mNum] = '\0';
    }
    return count;
}

//retrieve words(10 atmost)
//return count of words
int WinIme::Search(int offset) {
    assert(mNum > 0);
    return MatchWord(mpOffset[mNum - 1], mNum, offset);
}

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to