/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 of the License, or
* (at your option) 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, see .
*
*/
#include "common/std/algorithm.h"
#include "ags/shared/ac/words_dictionary.h"
#include "ags/shared/util/stream.h"
#include "ags/shared/util/string_compat.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
WordsDictionary::WordsDictionary()
: num_words(0)
, word(nullptr)
, wordnum(nullptr) {
}
WordsDictionary::~WordsDictionary() {
free_memory();
}
void WordsDictionary::allocate_memory(int wordCount) {
num_words = wordCount;
if (num_words > 0) {
word = new char *[wordCount];
word[0] = new char[wordCount * MAX_PARSER_WORD_LENGTH];
wordnum = new short[wordCount];
for (int i = 1; i < wordCount; i++) {
word[i] = word[0] + MAX_PARSER_WORD_LENGTH * i;
}
}
}
void WordsDictionary::free_memory() {
if (num_words > 0) {
delete[] word[0];
delete[] word;
delete[] wordnum;
word = nullptr;
wordnum = nullptr;
num_words = 0;
}
}
void WordsDictionary::sort() {
int aa, bb;
for (aa = 0; aa < num_words; aa++) {
for (bb = aa + 1; bb < num_words; bb++) {
if (((wordnum[aa] == wordnum[bb]) && (ags_stricmp(word[aa], word[bb]) > 0))
|| (wordnum[aa] > wordnum[bb])) {
short temp = wordnum[aa];
char tempst[30];
wordnum[aa] = wordnum[bb];
wordnum[bb] = temp;
snprintf(tempst, MAX_PARSER_WORD_LENGTH, "%s", word[aa]);
snprintf(word[aa], MAX_PARSER_WORD_LENGTH, "%s", word[bb]);
snprintf(word[bb], MAX_PARSER_WORD_LENGTH, "%s", tempst);
bb = aa;
}
}
}
}
int WordsDictionary::find_index(const char *wrem) {
int aa;
for (aa = 0; aa < num_words; aa++) {
if (ags_stricmp(wrem, word[aa]) == 0)
return aa;
}
return -1;
}
void decrypt_text(char *toenc, size_t buf_sz) {
int adx = 0;
const char *p_end = toenc + buf_sz;
while (toenc < p_end) {
toenc[0] -= _G(passwencstring)[adx];
if (toenc[0] == 0)
break;
adx++;
toenc++;
if (adx > 10)
adx = 0;
}
}
void read_string_decrypt(Stream *in, char *buf, size_t buf_sz) {
size_t len = in->ReadInt32();
size_t slen = MIN(buf_sz - 1, len);
in->Read(buf, slen);
if (len > slen)
in->Seek(len - slen);
decrypt_text(buf, slen);
buf[slen] = 0;
}
String read_string_decrypt(Stream *in, std::vector &dec_buf) {
size_t len = in->ReadInt32();
dec_buf.resize(len + 1);
in->Read(dec_buf.data(), len);
decrypt_text(dec_buf.data(), len);
dec_buf.back() = 0; // null terminate in case read string does not have one
return String(dec_buf.data());
}
void read_dictionary(WordsDictionary *dict, Stream *out) {
int ii;
dict->allocate_memory(out->ReadInt32());
for (ii = 0; ii < dict->num_words; ii++) {
read_string_decrypt(out, dict->word[ii], MAX_PARSER_WORD_LENGTH);
dict->wordnum[ii] = out->ReadInt16();
}
}
#if defined (OBSOLETE)
// TODO: not a part of wordsdictionary, move to obsoletes
void freadmissout(short *pptr, Stream *in) {
in->ReadArrayOfInt16(&pptr[0], 5);
in->ReadArrayOfInt16(&pptr[7], NUM_CONDIT - 7);
pptr[5] = pptr[6] = 0;
}
#endif
void encrypt_text(char *toenc) {
int adx = 0, tobreak = 0;
while (tobreak == 0) {
if (toenc[0] == 0)
tobreak = 1;
toenc[0] += _G(passwencstring)[adx];
adx++;
toenc++;
if (adx > 10)
adx = 0;
}
}
void write_string_encrypt(Stream *out, const char *s) {
int stlent = (int)strlen(s) + 1;
out->WriteInt32(stlent);
char *enc = ags_strdup(s);
encrypt_text(enc);
out->WriteArray(enc, stlent, 1);
free(enc);
}
void write_dictionary(WordsDictionary *dict, Stream *out) {
int ii;
out->WriteInt32(dict->num_words);
for (ii = 0; ii < dict->num_words; ii++) {
write_string_encrypt(out, dict->word[ii]);
out->WriteInt16(dict->wordnum[ii]);
}
}
} // namespace AGS3