/* -------------------------------------------------------------
dict.cpp (part of The KDE Dictionary Client)
Copyright (C) 2000-2001 Christian Gebauer
(C) by Matthias H�lzer 1998
This file is distributed under the Artistic License.
See LICENSE for details.
-------------------------------------------------------------
JobData used for data transfer between Client and Interface
DictAsyncClient all network related stuff happens here in asynchrous thread
DictInterface interface for DictAsyncClient, job management
------------------------------------------------------------- */
#include
#include "application.h"
#include "options.h"
#include "dict.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//********* JobData ******************************************
JobData::JobData(QueryType Ntype,bool NnewServer,TQString const& Nserver,int Nport,
int NidleHold, int Ntimeout, int NpipeSize, TQString const& Nencoding, bool NAuthEnabled,
TQString const& Nuser, TQString const& Nsecret, unsigned int NheadLayout)
: type(Ntype), error(ErrNoErr), canceled(false), numFetched(0), newServer(NnewServer),server(Nserver), port(Nport),
timeout(Ntimeout), pipeSize(NpipeSize), idleHold(NidleHold), encoding(Nencoding), authEnabled(NAuthEnabled),
user(Nuser), secret(Nsecret), headLayout(NheadLayout)
{}
//********* DictAsyncClient *************************************
DictAsyncClient::DictAsyncClient(int NfdPipeIn, int NfdPipeOut)
: job(0L), inputSize(10000), fdPipeIn(NfdPipeIn),
fdPipeOut(NfdPipeOut), tcpSocket(-1), idleHold(0)
{
input = new char[inputSize];
}
DictAsyncClient::~DictAsyncClient()
{
if (-1!=tcpSocket)
doQuit();
delete [] input;
}
void* DictAsyncClient::startThread(void* pseudoThis)
{
DictAsyncClient* newthis = (DictAsyncClient*) (pseudoThis);
if (0!=pthread_setcanceltype(PTHREAD_CANCEL_ENABLE,NULL))
qWarning("pthread_setcanceltype failed!");
if (0!= pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL))
qWarning("pthread_setcanceltype failed!");
signal(SIGPIPE,SIG_IGN); // ignore sigpipe
newthis->waitForWork();
return NULL;
}
void DictAsyncClient::insertJob(JobData *newJob)
{
if (!job) // don't overwrite existing job pointer
job = newJob;
}
void DictAsyncClient::removeJob()
{
job = 0L;
}
void DictAsyncClient::waitForWork()
{
fd_set fdsR,fdsE;
timeval tv;
int selectRet;
char buf;
while (true) {
if (tcpSocket != -1) { // we are connected, hold the connection for xx secs
FD_ZERO(&fdsR);
FD_SET(fdPipeIn, &fdsR);
FD_SET(tcpSocket, &fdsR);
FD_ZERO(&fdsE);
FD_SET(tcpSocket, &fdsE);
tv.tv_sec = idleHold;
tv.tv_usec = 0;
selectRet = KSocks::self()->select(FD_SETSIZE, &fdsR, NULL, &fdsE, &tv);
if (selectRet == 0) {
doQuit(); // nothing happend...
} else {
if (((selectRet > 0)&&(!FD_ISSET(fdPipeIn,&fdsR)))||(selectRet == -1))
closeSocket();
}
}
do {
FD_ZERO(&fdsR);
FD_SET(fdPipeIn, &fdsR);
} while (select(FD_SETSIZE, &fdsR, NULL, NULL, NULL)<0); // don't get tricked by signals
clearPipe();
if (job) {
if ((tcpSocket!=-1)&&(job->newServer))
doQuit();
codec = TQTextCodec::codecForName(job->encoding.latin1());
input[0] = 0; //terminate string
thisLine = input;
nextLine = input;
inputEnd = input;
timeout = job->timeout;
idleHold = job->idleHold;
if (tcpSocket==-1)
openConnection();
if (tcpSocket!=-1) { // connection is ready
switch (job->type) {
case JobData::TDefine :
define();
break;
case JobData::TGetDefinitions :
getDefinitions();
break;
case JobData::TMatch :
match();
break;
case JobData::TShowDatabases :
showDatabases();
break;
case JobData::TShowDbInfo :
showDbInfo();
break;
case JobData::TShowStrategies :
showStrategies();
break;
case JobData::TShowInfo :
showInfo();
break;
case JobData::TUpdate :
update();
}
}
clearPipe();
}
if (write(fdPipeOut,&buf,1) == -1) // emit stopped signal
::perror( "waitForJobs()" );
}
}
void DictAsyncClient::define()
{
TQString command;
job->defines.clear();
TQStringList::iterator it;
for (it = job->databases.begin(); it != job->databases.end(); ++it) {
command = "define ";
command += *it;
command += " \"";
command += job->query;
command += "\"\r\n";
job->defines.append(command);
}
if (!getDefinitions())
return;
if (job->numFetched == 0) {
job->strategy = ".";
if (!match())
return;
job->result = TQString();
if (job->numFetched == 0) {
resultAppend("\n\n");
resultAppend(i18n("No definitions found for \'%1'.").tqarg(job->query));
resultAppend("
\n
\n\n");
resultAppend(i18n("No definitions found for \'%1\'. Perhaps you mean:").tqarg(job->query));
resultAppend("
\n\n");
TQString lastDb;
TQStringList::iterator it;
for (it = job->matches.begin(); it != job->matches.end(); ++it) {
int pos = (*it).find(' ');
if (pos != -1) {
if (lastDb != (*it).left(pos)) {
if (lastDb.length() > 0)
resultAppend("\n");
lastDb = (*it).left(pos);
resultAppend("");
resultAppend(lastDb);
resultAppend(": | ");
}
if ((*it).length() > (unsigned int)pos+2) {
resultAppend("");
resultAppend((*it).mid(pos+2, (*it).length()-pos-3));
resultAppend(" ");
}
}
}
resultAppend("\n |
\n