|
|
//==========================================================================================
|
|
|
//
|
|
|
// File : kvi_config.cpp
|
|
|
// Last major modification : Thu Jan 14 1999 18:03:59 by Szymon Stefanek
|
|
|
//
|
|
|
// This file is part of the KVirc irc client distribution
|
|
|
// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot net)
|
|
|
//
|
|
|
// 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 opinion) 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. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
//
|
|
|
//==========================================================================================
|
|
|
|
|
|
#define __KVILIB__
|
|
|
|
|
|
#include "kvi_config.h"
|
|
|
#include "kvi_fileutils.h"
|
|
|
#include "kvi_pixmap.h"
|
|
|
#include "kvi_msgtype.h"
|
|
|
#include "kvi_stringconversion.h"
|
|
|
#include "kvi_memmove.h"
|
|
|
#include "kvi_malloc.h"
|
|
|
#include "kvi_file.h"
|
|
|
|
|
|
|
|
|
KviConfig::KviConfig(const TQString &filename,FileMode f,bool bLocal8Bit)
|
|
|
{
|
|
|
m_bLocal8Bit = bLocal8Bit;
|
|
|
m_szFileName = filename;
|
|
|
m_bDirty = false;
|
|
|
m_szGroup = KVI_CONFIG_DEFAULT_GROUP;
|
|
|
m_bPreserveEmptyGroups = false;
|
|
|
m_bReadOnly = (f == KviConfig::Read);
|
|
|
m_pDict = new KviPointerHashTable<TQString,KviConfigGroup>(17,false);
|
|
|
m_pDict->setAutoDelete(true);
|
|
|
if(f != KviConfig::Write)load();
|
|
|
}
|
|
|
|
|
|
KviConfig::KviConfig(const char* filename,FileMode f,bool bLocal8Bit)
|
|
|
{
|
|
|
m_bLocal8Bit = bLocal8Bit;
|
|
|
m_szFileName = TQString::fromUtf8(filename);
|
|
|
m_bDirty = false;
|
|
|
m_szGroup = KVI_CONFIG_DEFAULT_GROUP;
|
|
|
m_bPreserveEmptyGroups = false;
|
|
|
m_bReadOnly = (f == KviConfig::Read);
|
|
|
m_pDict = new KviPointerHashTable<TQString,KviConfigGroup>(17,false);
|
|
|
m_pDict->setAutoDelete(true);
|
|
|
if(f != KviConfig::Write)load();
|
|
|
}
|
|
|
|
|
|
|
|
|
KviConfig::~KviConfig()
|
|
|
{
|
|
|
if(m_bDirty)save();
|
|
|
delete m_pDict;
|
|
|
}
|
|
|
|
|
|
void KviConfig::clear()
|
|
|
{
|
|
|
delete m_pDict;
|
|
|
m_pDict = new KviPointerHashTable<TQString,KviConfigGroup>(17,false);
|
|
|
m_pDict->setAutoDelete(true);
|
|
|
m_bDirty = false;
|
|
|
m_szGroup = KVI_CONFIG_DEFAULT_GROUP;
|
|
|
}
|
|
|
|
|
|
void KviConfig::clearGroup(const TQString & szGroup)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
m_pDict->remove(szGroup);
|
|
|
if(!m_pDict->find(m_szGroup))m_szGroup = KVI_CONFIG_DEFAULT_GROUP; //removed the current one
|
|
|
}
|
|
|
|
|
|
void KviConfig::clearKey(const TQString & szKey)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
p_group->remove(szKey);
|
|
|
if(p_group->count() == 0)clearGroup(m_szGroup);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
void KviConfig::getContentsString(KviStr &buffer)
|
|
|
{
|
|
|
buffer = __tr("Contents of config file ");
|
|
|
buffer.append(m_szFileName.ptr());
|
|
|
buffer.append('\n');
|
|
|
int sections = 0;
|
|
|
int keys = 0;
|
|
|
KviPointerHashTableIterator<TQString,KviStrDict> it(*m_pDict);
|
|
|
while(it.current()){
|
|
|
buffer.append(" Section [");
|
|
|
buffer.append(it.currentKey());
|
|
|
buffer.append("]\n");
|
|
|
int sectionKeys = 0;
|
|
|
KviPointerHashTableIterator<TQString,KviStr> it2(*it.current());
|
|
|
while(it2.current()){
|
|
|
buffer.append(" Key [");
|
|
|
buffer.append(it2.currentKey());
|
|
|
buffer.append("] : ");
|
|
|
buffer.append(it2.current()->ptr());
|
|
|
buffer.append('\n');
|
|
|
++it2;
|
|
|
++sectionKeys;
|
|
|
++keys;
|
|
|
}
|
|
|
KviStr tmp(KviStr::Format,__tr(" Total: %d keys"),sectionKeys);
|
|
|
buffer.append(tmp);
|
|
|
buffer.append('\n');
|
|
|
++it;
|
|
|
++sections;
|
|
|
}
|
|
|
KviStr tmp(KviStr::Format,__tr("Total: %d keys in %d sections"),keys,sections);
|
|
|
buffer.append(tmp);
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#define LOAD_BLOCK_SIZE 32768
|
|
|
|
|
|
bool KviConfig::load()
|
|
|
{
|
|
|
// this is really faster than the old version :)
|
|
|
|
|
|
// open the file
|
|
|
KviFile f(m_szFileName);
|
|
|
if(!f.openForReading())return false;
|
|
|
|
|
|
KviStr tmp;
|
|
|
KviConfigGroup * p_group = 0;
|
|
|
|
|
|
int iLoadBlockSize = LOAD_BLOCK_SIZE;
|
|
|
|
|
|
char * buffer = (char *)kvi_malloc(iLoadBlockSize * sizeof(char));
|
|
|
|
|
|
int toRead;
|
|
|
int readedLen;
|
|
|
int remainingLen = 0;
|
|
|
|
|
|
char * p = buffer; // start writing to the beginning of the buffer
|
|
|
|
|
|
do {
|
|
|
// compute the length to read
|
|
|
toRead = iLoadBlockSize - remainingLen;
|
|
|
if(toRead < 1)
|
|
|
{
|
|
|
// ops... a string longer than iLoadBlockSize - 1 chars
|
|
|
iLoadBlockSize += LOAD_BLOCK_SIZE;
|
|
|
int iOffset = p - buffer;
|
|
|
buffer = (char *)kvi_realloc(buffer,iLoadBlockSize * sizeof(char));
|
|
|
p = buffer + iOffset;
|
|
|
toRead += LOAD_BLOCK_SIZE;
|
|
|
}
|
|
|
|
|
|
// do read
|
|
|
readedLen = f.readBlock(p,toRead);
|
|
|
if(readedLen < toRead)
|
|
|
{
|
|
|
// check for errors
|
|
|
if(readedLen <= 0)
|
|
|
{
|
|
|
if(readedLen < 0)
|
|
|
{
|
|
|
// error at all
|
|
|
f.close();
|
|
|
kvi_free(buffer);
|
|
|
return true; // nothing more to parse anyway
|
|
|
} else {
|
|
|
// just a zero byte read
|
|
|
if(remainingLen == 0)
|
|
|
{
|
|
|
// there was nothing in the buffer
|
|
|
f.close(); // nothing to parse anyway
|
|
|
kvi_free(buffer);
|
|
|
return true;
|
|
|
}
|
|
|
// there is something in the buffer but we have readed 0 bytes
|
|
|
// this usually means that the last line in the file has no trailing newline
|
|
|
// ...we just fake it :)
|
|
|
*p = '\n';
|
|
|
readedLen = 1;
|
|
|
}
|
|
|
} else {
|
|
|
// just readed something but less than expected
|
|
|
// check if the last readed char is a newline
|
|
|
// if it isn't , fake it
|
|
|
if(*(p + readedLen - 1) != '\n')
|
|
|
{
|
|
|
*(p + readedLen) = '\n';
|
|
|
readedLen++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
// compute the end pointer
|
|
|
char * endp = p + readedLen;
|
|
|
|
|
|
p = buffer; // start from beginning of the data buffer at all
|
|
|
// begin of the current string
|
|
|
char * begin = p;
|
|
|
|
|
|
// and loop
|
|
|
while(p < endp)
|
|
|
{
|
|
|
// find a newline
|
|
|
if(*p != '\n')
|
|
|
{
|
|
|
p++;
|
|
|
continue;
|
|
|
}
|
|
|
// newline!
|
|
|
*p = 0;
|
|
|
// now begin points to the string that terminates in p
|
|
|
// skip leading whitespace
|
|
|
while((*begin == '\t') || (*begin == ' '))begin++;
|
|
|
|
|
|
if(p == begin)
|
|
|
{
|
|
|
// empty line
|
|
|
p++;
|
|
|
begin = p;
|
|
|
continue;
|
|
|
}
|
|
|
// now p > begin
|
|
|
// check if there are trailing spaces (include CR so CRLF is trimmed too)
|
|
|
char * trail = p - 1;
|
|
|
|
|
|
p++;
|
|
|
|
|
|
while(trail >= begin)
|
|
|
{
|
|
|
if((*trail == '\r') || (*trail == '\t') || (*trail == ' '))*trail = 0;
|
|
|
else break;
|
|
|
trail--;
|
|
|
}
|
|
|
|
|
|
// yeah, have some data in this line :D
|
|
|
switch(*begin)
|
|
|
{
|
|
|
case 0:
|
|
|
// empty line
|
|
|
break;
|
|
|
case '#':
|
|
|
// comment: just skip it
|
|
|
break;
|
|
|
case '[':
|
|
|
// group ?
|
|
|
begin++;
|
|
|
if(*begin && (*begin != ']'))
|
|
|
{
|
|
|
char * z = begin;
|
|
|
#define COMPAT_WITH_OLD_CONFIGS
|
|
|
#ifdef COMPAT_WITH_OLD_CONFIGS
|
|
|
// run to the end of the string
|
|
|
while(*z)z++;
|
|
|
// run back to the trailing ']'
|
|
|
while((z > begin) && (*z != ']'))z--;
|
|
|
// if it is not ther just run back to the end of the string
|
|
|
if(*z != ']')while(*z)z++;
|
|
|
#else
|
|
|
// new configs have it always encoded properly
|
|
|
while(*z && (*z != ']'))z++;
|
|
|
#endif
|
|
|
*z = 0;
|
|
|
tmp.hexDecode(begin);
|
|
|
tmp.stripRightWhiteSpace(); // no external spaces in group names
|
|
|
|
|
|
if(!tmp.isEmpty())
|
|
|
{
|
|
|
TQString szGroup = m_bLocal8Bit ?
|
|
|
TQString::fromLocal8Bit(tmp.ptr(),tmp.len()) :
|
|
|
TQString::fromUtf8(tmp.ptr(),tmp.len());
|
|
|
p_group = m_pDict->find(szGroup);
|
|
|
if(!p_group)
|
|
|
{
|
|
|
p_group = new KviConfigGroup(17,false);
|
|
|
p_group->setAutoDelete(true);
|
|
|
m_pDict->insert(szGroup,p_group);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
{
|
|
|
// real data ?
|
|
|
char * z = begin;
|
|
|
while(*z && (*z != '='))z++;
|
|
|
if(*z && (z != begin))
|
|
|
{
|
|
|
*z = 0;
|
|
|
tmp.hexDecode(begin);
|
|
|
tmp.stripRightWhiteSpace(); // No external spaces at all in keys
|
|
|
if(!tmp.isEmpty())
|
|
|
{
|
|
|
TQString szKey = m_bLocal8Bit ?
|
|
|
TQString::fromLocal8Bit(tmp.ptr(),tmp.len()) :
|
|
|
TQString::fromUtf8(tmp.ptr(),tmp.len());
|
|
|
z++;
|
|
|
while(*z && ((*z == ' ') || (*z == '\t')))z++;
|
|
|
if(*z)
|
|
|
{
|
|
|
tmp.hexDecode(z);
|
|
|
TQString * pVal = new TQString( m_bLocal8Bit ?
|
|
|
TQString::fromLocal8Bit(tmp.ptr(),tmp.len()) :
|
|
|
TQString::fromUtf8(tmp.ptr(),tmp.len())
|
|
|
);
|
|
|
if(!p_group)
|
|
|
{
|
|
|
// ops...we're missing a group
|
|
|
// use the default one
|
|
|
p_group = new KviConfigGroup(17,false);
|
|
|
p_group->setAutoDelete(true);
|
|
|
m_pDict->insert(KVI_CONFIG_DEFAULT_GROUP,p_group);
|
|
|
}
|
|
|
p_group->replace(szKey,pVal);
|
|
|
} else {
|
|
|
// we in fact need this (mercy :D)
|
|
|
// otherwise the empty options will be treated as non-existing ones
|
|
|
// and will get the defaults (which is bad)
|
|
|
TQString * pVal = new TQString(TQString());
|
|
|
p_group->replace(szKey,pVal);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
begin = p;
|
|
|
}
|
|
|
if(begin != endp)
|
|
|
{
|
|
|
// there is data with no trailing newline in the buffer
|
|
|
remainingLen = endp-begin;
|
|
|
if(buffer != begin)
|
|
|
{
|
|
|
kvi_memmove(buffer,begin,remainingLen);
|
|
|
p = buffer + remainingLen;
|
|
|
} // else p remains where it is
|
|
|
} else {
|
|
|
p = buffer;
|
|
|
}
|
|
|
} while(readedLen == toRead);
|
|
|
|
|
|
f.close();
|
|
|
kvi_free(buffer);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
|
|
bool KviConfig::load()
|
|
|
{
|
|
|
TQFile f(m_szFileName);
|
|
|
if(!f.open(IO_ReadOnly))return false;
|
|
|
|
|
|
|
|
|
KviConfigGroup * p_group = 0;
|
|
|
|
|
|
KviStr dataLine;
|
|
|
bool bContinue;
|
|
|
|
|
|
do {
|
|
|
bContinue = kvi_readLine(&f,dataLine);
|
|
|
dataLine.stripWhiteSpace();
|
|
|
if(dataLine.hasData())
|
|
|
{
|
|
|
switch(*(dataLine.ptr()))
|
|
|
{
|
|
|
case '#':
|
|
|
// just skip it , it is a comment
|
|
|
break;
|
|
|
case '[':
|
|
|
{
|
|
|
//set the group
|
|
|
dataLine.cutLeft(1);
|
|
|
dataLine.cutRight(1);
|
|
|
dataLine.hexDecode();
|
|
|
if(dataLine.hasData())
|
|
|
{
|
|
|
TQString szUtf8 = TQString::fromUtf8(dataLine.ptr());
|
|
|
p_group = m_pDict->find(szUtf8);
|
|
|
|
|
|
if(!p_group)
|
|
|
{
|
|
|
p_group = new KviConfigGroup(17,false);
|
|
|
p_group->setAutoDelete(true);
|
|
|
m_pDict->insert(szUtf8,p_group);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
{
|
|
|
//data entry...split in two...
|
|
|
KviStr name=dataLine.getToken('=');
|
|
|
name.stripRightWhiteSpace(); // strip any whitespace added externally
|
|
|
name.hexDecode();
|
|
|
if(name.hasData())
|
|
|
{
|
|
|
dataLine.stripLeftWhiteSpace(); // strip any whitespace added externally
|
|
|
dataLine.hexDecode();
|
|
|
//insert (replace items if needed)
|
|
|
TQString *p_data=new TQString(TQString::fromUtf8(dataLine.ptr()));
|
|
|
if(!p_group)
|
|
|
{
|
|
|
// ops...we're missing a group
|
|
|
// use the default one
|
|
|
p_group = new KviConfigGroup(17,false);
|
|
|
p_group->setAutoDelete(true);
|
|
|
m_pDict->insert(KVI_CONFIG_DEFAULT_GROUP,p_group);
|
|
|
}
|
|
|
TQString szName = TQString::fromUtf8(name.ptr());
|
|
|
p_group->replace(szName,p_data);
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
} while (bContinue);
|
|
|
|
|
|
f.close();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool KviConfig::save()
|
|
|
{
|
|
|
static unsigned char encode_table[256]=
|
|
|
{
|
|
|
// 000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015
|
|
|
// NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
|
|
|
1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,
|
|
|
// 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031
|
|
|
// DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
|
|
|
1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,
|
|
|
// 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047
|
|
|
// ! " # $ % & ' ( ) * + , - . /
|
|
|
1 ,0 ,0 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063
|
|
|
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,0 ,
|
|
|
// 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079
|
|
|
// @ A B C D E F G H I J K L M N O
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095
|
|
|
// P Q R S T U V W X Y Z [ \ ] ^ _
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,0 ,0 ,
|
|
|
// 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111
|
|
|
// ` a b c d e f g h i j k l m n o
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
|
|
// p q r s t u v w x y z { | } ~
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
|
|
//
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
|
|
//
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
|
|
//
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
|
|
//
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
|
|
// <09> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20>
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
|
|
// <09> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20>
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
|
|
|
// <09> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20>
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
|
|
// 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
|
|
|
// <09> <20> <20> <20> <20> <20> <20> <20>
|
|
|
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
|
|
|
};
|
|
|
|
|
|
|
|
|
if(m_bReadOnly)return false;
|
|
|
|
|
|
KviFile f(m_szFileName);
|
|
|
if(!f.openForWriting())return false;
|
|
|
if(f.writeBlock("# KVIrc configuration file\n",27) != 27)return false;
|
|
|
|
|
|
KviPointerHashTableIterator<TQString,KviConfigGroup> it(*m_pDict);
|
|
|
while (it.current())
|
|
|
{
|
|
|
if((it.current()->count() != 0) || (m_bPreserveEmptyGroups))
|
|
|
{
|
|
|
KviStr group(m_bLocal8Bit ? KviTQString::toLocal8Bit(it.currentKey()) : KviTQString::toUtf8(it.currentKey()));
|
|
|
group.hexEncodeWithTable(encode_table);
|
|
|
|
|
|
if(!f.putChar('['))return false;
|
|
|
if(f.writeBlock(group.ptr(),group.len()) < (int) group.len())return false;
|
|
|
if(f.writeBlock("]\n",2) < 2)return false;
|
|
|
|
|
|
KviConfigGroup * dict = (KviConfigGroup *)it.current();
|
|
|
KviConfigGroupIterator it2(*dict);
|
|
|
|
|
|
KviStr szName,szValue;
|
|
|
while(TQString * p_str = it2.current())
|
|
|
{
|
|
|
szName = m_bLocal8Bit ? KviTQString::toLocal8Bit(it2.currentKey()) : KviTQString::toUtf8(it2.currentKey());
|
|
|
szValue = m_bLocal8Bit ? KviTQString::toLocal8Bit(*p_str) : KviTQString::toUtf8(*p_str);
|
|
|
szName.hexEncodeWithTable(encode_table);
|
|
|
szValue.hexEncodeWhiteSpace();
|
|
|
|
|
|
if(f.writeBlock(szName.ptr(),szName.len()) < (int) szName.len())return false;
|
|
|
if(!f.putChar('='))return false;
|
|
|
if(f.writeBlock(szValue.ptr(),szValue.len()) < (int) szValue.len())return false;
|
|
|
if(!f.putChar('\n'))return false;
|
|
|
++it2;
|
|
|
}
|
|
|
}
|
|
|
++it;
|
|
|
}
|
|
|
f.close();
|
|
|
m_bDirty = false;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
void KviConfig::setGroup(const TQString & szGroup)
|
|
|
{
|
|
|
m_szGroup = szGroup;
|
|
|
if(m_bPreserveEmptyGroups)
|
|
|
{
|
|
|
if(!hasGroup(szGroup))
|
|
|
{
|
|
|
getCurrentGroup(); // we need it to be created.
|
|
|
m_bDirty = true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool KviConfig::hasKey(const TQString & szKey)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
return (p_group->find(szKey) != 0);
|
|
|
}
|
|
|
|
|
|
bool KviConfig::hasGroup(const TQString & szGroup)
|
|
|
{
|
|
|
return (m_pDict->find(szGroup) != 0);
|
|
|
}
|
|
|
|
|
|
KviConfigGroup * KviConfig::getCurrentGroup()
|
|
|
{
|
|
|
if(m_szGroup.isEmpty())m_szGroup = KVI_CONFIG_DEFAULT_GROUP;
|
|
|
KviConfigGroup * p_group = m_pDict->find(m_szGroup);
|
|
|
if(!p_group)
|
|
|
{
|
|
|
//create the group
|
|
|
p_group = new KviConfigGroup(17,false);
|
|
|
p_group->setAutoDelete(true);
|
|
|
m_pDict->insert(m_szGroup,p_group);
|
|
|
}
|
|
|
return p_group;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// KviStr
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,const TQString & szValue)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString *p_data=new TQString(szValue);
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
// FIXME: #warning "We have probs here ?"
|
|
|
|
|
|
TQString KviConfig::readEntry(const TQString & szKey,const TQString & szDefault)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(!p_str)
|
|
|
{
|
|
|
m_szStrBuffer = szDefault;
|
|
|
} else {
|
|
|
m_szStrBuffer = *p_str;
|
|
|
}
|
|
|
return m_szStrBuffer;
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////// TQString
|
|
|
|
|
|
/*
|
|
|
TQString KviConfig::readTQStringEntry(const char *szKey,const TQString &szDefault)
|
|
|
{
|
|
|
KviStrDict * p_group = getCurrentGroup();
|
|
|
KviStr * p_str = p_group->find(szKey);
|
|
|
if(!p_str)return szDefault;
|
|
|
return TQString::fromUtf8(p_str->ptr());
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
/*
|
|
|
void KviConfig::writeEntry(const char *szKey,const TQString &szValue)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviStrDict * p_group = getCurrentGroup();
|
|
|
p_group->replace(szKey,new KviStr(szValue.utf8().data()));
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
////////////////////////////////// TQStringList
|
|
|
|
|
|
static TQString g_szConfigStringListSeparator(",\\[ITEM],");
|
|
|
|
|
|
TQStringList KviConfig::readStringListEntry(const TQString & szKey,const TQStringList &list)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(!p_str)return list;
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
return p_str->split(g_szConfigStringListSeparator);
|
|
|
#else
|
|
|
return TQStringList::split(g_szConfigStringListSeparator,*p_str);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,const TQStringList &list)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString *p_data=new TQString(list.join(g_szConfigStringListSeparator));
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// KviValueList<int>
|
|
|
|
|
|
KviValueList<int> KviConfig::readIntListEntry(const TQString & szKey,const KviValueList<int> &list)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(!p_str)
|
|
|
{
|
|
|
//debug("Returning default list for group %s and key %s",m_szGroup.latin1(),szKey.latin1());
|
|
|
return list;
|
|
|
}
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
TQStringList sl = p_str->split(",");
|
|
|
#else
|
|
|
TQStringList sl = TQStringList::split(",",*p_str);
|
|
|
#endif
|
|
|
KviValueList<int> ret;
|
|
|
|
|
|
//debug("Got option list for group %s and key %s: %s",m_szGroup.latin1(),szKey.latin1(),p_str->latin1());
|
|
|
|
|
|
for(TQStringList::Iterator it = sl.begin();it != sl.end();++it)
|
|
|
{
|
|
|
bool bOk;
|
|
|
int iTmp = (*it).toInt(&bOk);
|
|
|
if(bOk)ret.append(iTmp);
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,const KviValueList<int> &list)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
KviStr szData;
|
|
|
for(KviValueList<int>::ConstIterator it = list.begin();it != list.end();++it)
|
|
|
{
|
|
|
if(szData.hasData())szData.append(',');
|
|
|
szData.append(KviStr::Format,"%d",*it);
|
|
|
}
|
|
|
//debug("Writing option list for group %s and key %s: %s",m_szGroup.latin1(),szKey.latin1(),szData.ptr());
|
|
|
|
|
|
p_group->replace(szKey,new TQString(szData.ptr()));
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// KviPixmap
|
|
|
|
|
|
// FIXME: #warning "Spaces in image names ?"
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,const KviPixmap &pixmap)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString *p_data=new TQString();
|
|
|
KviStringConversion::toString(pixmap,*p_data);
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
KviPixmap KviConfig::readPixmapEntry(const TQString & szKey,const KviPixmap &pixDef)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(p_str)
|
|
|
{
|
|
|
KviPixmap ret("");
|
|
|
return KviStringConversion::fromString(*p_str,ret) ? ret : pixDef;
|
|
|
} else {
|
|
|
return pixDef;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// KviMsgType
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,const KviMsgType &msg)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString szData;
|
|
|
KviStringConversion::toString(msg,szData);
|
|
|
p_group->replace(szKey,new TQString(szData));
|
|
|
}
|
|
|
|
|
|
KviMsgType KviConfig::readMsgTypeEntry(const TQString & szKey,const KviMsgType &msgDef)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(!p_str)return msgDef;
|
|
|
KviMsgType ret = msgDef;
|
|
|
KviStringConversion::fromString(*p_str,ret);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// TQColor
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,const TQColor &clr)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
KviStr szData(KviStr::Format,"%d,%d,%d",clr.red(),clr.green(),clr.blue());
|
|
|
p_group->replace(szKey,new TQString(szData.ptr()));
|
|
|
}
|
|
|
|
|
|
TQColor KviConfig::readColorEntry(const TQString & szKey,const TQColor &clr)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQColor color(clr);
|
|
|
TQString * pointer_that_IS_initialized = p_group->find(szKey);
|
|
|
|
|
|
|
|
|
if(pointer_that_IS_initialized)
|
|
|
{
|
|
|
|
|
|
KviStr str(*pointer_that_IS_initialized);
|
|
|
str.stripLeftWhiteSpace();
|
|
|
|
|
|
KviStr red,green,blue;
|
|
|
|
|
|
str.getToken(red,',');
|
|
|
str.getToken(green,',');
|
|
|
str.getToken(blue,',');
|
|
|
|
|
|
if((red.isUnsignedNum())&&(green.isUnsignedNum())&&(blue.isUnsignedNum())){
|
|
|
bool bOk;
|
|
|
int r = red.toInt(&bOk) % 256;
|
|
|
int g = green.toInt(&bOk) % 256;
|
|
|
int b = blue.toInt(&bOk) % 256;
|
|
|
if(r < 0)r = -r;
|
|
|
if(g < 0)g = -g;
|
|
|
if(b < 0)b = -b;
|
|
|
color.setRgb(r,g,b);
|
|
|
}
|
|
|
}
|
|
|
return color;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// TQFont
|
|
|
|
|
|
void KviConfig::getFontProperties(KviStr & buffer,TQFont *fnt)
|
|
|
{
|
|
|
TQString tmp;
|
|
|
KviStringConversion::toString(*fnt,tmp);
|
|
|
buffer = tmp;
|
|
|
}
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,TQFont &fnt)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString *p_data = new TQString();
|
|
|
KviStringConversion::toString(fnt,*p_data);
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
|
|
|
void KviConfig::setFontProperties(KviStr & str,TQFont *fnt)
|
|
|
{
|
|
|
KviStringConversion::fromString(str.ptr(),*fnt);
|
|
|
}
|
|
|
|
|
|
TQFont KviConfig::readFontEntry(const TQString & szKey,const TQFont &fnt)
|
|
|
{
|
|
|
TQFont font(fnt);
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(p_str)
|
|
|
{
|
|
|
//FontEntry=Arial,12,9,0,100,italic,underline,strikeout,
|
|
|
KviStr str(*p_str);
|
|
|
str.stripLeftWhiteSpace();
|
|
|
setFontProperties(str,&font);
|
|
|
}
|
|
|
return font;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// bool
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,bool bTrue)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString *p_data = new TQString(bTrue ? "true" : "false");
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
bool KviConfig::readBoolEntry(const TQString & szKey,bool bTrue)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(!p_str)return bTrue;
|
|
|
static TQString szTrue = "true";
|
|
|
return (KviTQString::toLower(*p_str) == szTrue);
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// TQRect
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,const TQRect &rct)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString szBuf;
|
|
|
KviStringConversion::toString(rct,szBuf);
|
|
|
p_group->replace(szKey,new TQString(szBuf));
|
|
|
}
|
|
|
|
|
|
TQRect KviConfig::readRectEntry(const TQString & szKey,const TQRect &rct)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * str = p_group->find(szKey);
|
|
|
if(!str)return rct;
|
|
|
TQRect ret;
|
|
|
return KviStringConversion::fromString(*str,ret) ? ret : rct;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// unsigned short
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,unsigned short usValue)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString *p_data = new TQString();
|
|
|
p_data->setNum(usValue);
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
unsigned short int KviConfig::readUShortEntry(const TQString & szKey,unsigned short int usDefault)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(!p_str)return usDefault;
|
|
|
bool bOk;
|
|
|
unsigned short int usVal=p_str->toUShort(&bOk);
|
|
|
return bOk ? usVal : usDefault;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
////////////////////////////////// unsigned long
|
|
|
|
|
|
Unused code
|
|
|
void KviConfig::writeEntry(const char *szKey,unsigned long lValue)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviStrDict * p_group = getCurrentGroup();
|
|
|
KviStr *p_data = new KviStr();
|
|
|
p_data->setNum(lValue);
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
unsigned long KviConfig::readULongEntry(const char *szKey,unsigned long lDefault)
|
|
|
{
|
|
|
KviStrDict * p_group = getCurrentGroup();
|
|
|
KviStr * p_str = p_group->find(szKey);
|
|
|
if(!p_str)return lDefault;
|
|
|
bool bOk;
|
|
|
unsigned long lVal=p_str->toULong(&bOk);
|
|
|
return bOk ? lVal : lDefault;
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
////////////////////////////////// int
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,int iValue)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString *p_data = new TQString();
|
|
|
p_data->setNum(iValue);
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
int KviConfig::readIntEntry(const TQString & szKey,int iDefault)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(!p_str)return iDefault;
|
|
|
bool bOk;
|
|
|
int iVal=p_str->toInt(&bOk);
|
|
|
return bOk ? iVal : iDefault;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// unsigned int
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,unsigned int iValue)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString *p_data = new TQString();
|
|
|
p_data->setNum(iValue);
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
unsigned int KviConfig::readUIntEntry(const TQString & szKey,unsigned int iDefault)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(!p_str)return iDefault;
|
|
|
bool bOk;
|
|
|
unsigned int iVal=p_str->toUInt(&bOk);
|
|
|
return bOk ? iVal : iDefault;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// char
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,char iValue)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_data = new TQString();
|
|
|
p_data->setNum(iValue);
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
char KviConfig::readCharEntry(const TQString & szKey,char iDefault)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(!p_str)return iDefault;
|
|
|
bool bOk;
|
|
|
char iVal=(char)p_str->toInt(&bOk);
|
|
|
return bOk ? iVal : iDefault;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////// unsigned char
|
|
|
|
|
|
void KviConfig::writeEntry(const TQString & szKey,unsigned char iValue)
|
|
|
{
|
|
|
m_bDirty = true;
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString *p_data = new TQString();
|
|
|
p_data->setNum(iValue);
|
|
|
p_group->replace(szKey,p_data);
|
|
|
}
|
|
|
|
|
|
unsigned char KviConfig::readUCharEntry(const TQString & szKey,unsigned char iDefault)
|
|
|
{
|
|
|
KviConfigGroup * p_group = getCurrentGroup();
|
|
|
TQString * p_str = p_group->find(szKey);
|
|
|
if(!p_str)return iDefault;
|
|
|
bool bOk;
|
|
|
unsigned char iVal=(unsigned char)p_str->toUInt(&bOk);
|
|
|
return bOk ? iVal : iDefault;
|
|
|
}
|
|
|
|
|
|
|
|
|
#ifdef COMPILE_ON_WINDOWS
|
|
|
|
|
|
// On windows we need to override new and delete operators
|
|
|
// to ensure that always the right new/delete pair is called for an object instance
|
|
|
// This bug is present in all the classes exported by a module that
|
|
|
// can be instantiated/destroyed from external modules.
|
|
|
// (this is a well known bug described in Q122675 of MSDN)
|
|
|
|
|
|
void * KviConfig::operator new(size_t tSize)
|
|
|
{
|
|
|
return kvi_malloc(tSize);
|
|
|
}
|
|
|
|
|
|
void KviConfig::operator delete(void * p)
|
|
|
{
|
|
|
kvi_free(p);
|
|
|
}
|
|
|
|
|
|
#endif
|