/* This file is a part of WordExtract project
*
* Copyright (C) 2009 Borisov Alexandr
*
* 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.
*
* 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
#include
#include
#include "mainwin.h"
#include "main.h"
#include "word.h"
#include "dict.h"
Word *words;
SortedWords user_words;
static SortedWords sorted = {0, NULL};
static Word *find_word(Word *, const char *);
/*third argument of find_parent() should be NULL when func is to be called*/
static void find_parent(Word *, const Word *, Word **);
static void sort_words(const Word *);
static Word *get_the_rightest(Word *);
static inline char *wordcpy(char *);
static inline void free_word(Word *);
unsigned int get_words_count(const Word *root)
{
unsigned int cnt = 0;
if (!root)
return 0;
else {
cnt += get_words_count(root->lsibl);
cnt += get_words_count(root->rsibl);
cnt++;
return cnt;
}
}
void del_word(Word **root, char *word)
{
Word *node, *parent = NULL;
Word **parent_leaf = NULL;
node = find_word(*root, word);
find_parent(*root, node, &parent);
if ((parent)&&(parent->lsibl == node))
parent_leaf = &parent->lsibl;
else if ((parent)&&(parent->rsibl == node))
parent_leaf = &parent->rsibl;
/*NOTE that (root == node) is a special case (without parent)*/
if ((!node->lsibl)&&(!node->rsibl)) {
if (parent)
*parent_leaf = NULL;
else
*root = NULL;
free_word(node);
return ;
}
if ((node->lsibl)&&(!node->rsibl)) {
if (parent)
*parent_leaf = node->lsibl;
else
*root = node->lsibl;
free_word(node);
} else if ((!node->lsibl)&&(node->rsibl)) {
if (parent)
*parent_leaf = node->rsibl;
else
*root = node->rsibl;
free_word(node);
} else {
Word *temp;
temp = get_the_rightest(node->lsibl);
temp->rsibl = node->rsibl;
if (parent)
*parent_leaf = node->lsibl;
else
*root = node->lsibl;
free_word(node);
}
}
Word *add_word(Word *root, char *word)
{
int cond;
if (!root) {
root = malloc(sizeof(Word));
root->word = wordcpy(word);
root->lsibl = root->rsibl = NULL;
}
else {
cond = strcmp(word, root->word);
if (cond > 0)
root->rsibl = add_word(root->rsibl, word);
else if (cond < 0)
root->lsibl = add_word(root->lsibl, word);
}
return root;
}
static Word *find_word(Word *root, const char *word)
{
int cond;
if (root) {
cond = strcmp(word, root->word);
if (cond > 0)
return find_word(root->rsibl, word);
else if (cond < 0)
return find_word(root->lsibl, word);
else
return root;
} else
return NULL;
}
static void find_parent(Word *root, const Word *sibling, Word **parent)
{
if (root) {
if (*parent)
return ;
if (root->lsibl != sibling)
find_parent(root->lsibl, sibling, parent);
else {
*parent = root;
return ;
}
if (*parent)
return ;
if (root->rsibl != sibling)
find_parent(root->rsibl, sibling, parent);
else{
*parent = root;
return ;
}
}
}
SortedWords get_sorted(Word *root)
{
unsigned int cnt;
cnt = get_words_count(root);
sorted.count = cnt;
sorted.by_az = NULL;
if (cnt) {
sorted.by_az = malloc(cnt*sizeof(char*));
sort_words(root);
sorted.by_az = sorted.by_az - cnt;
}
return sorted;
}
static void sort_words(const Word *root)
{
if (root) {
sort_words(root->lsibl);
*sorted.by_az = root->word;
sorted.by_az++;
sort_words(root->rsibl);
}
}
void save_words(FILE *tofile, SortedWords words, SaveOpt options)
{
int i, j;
char format[10] = {0};
sprintf(format, "%%-%us", options.col_width);
i = 0;
while (i < words.count) {
for (j = 0; (j < options.columns)&&(i < words.count); j++) {
if (j == options.columns-1)
fprintf(tofile, "%s\n", *words.by_az);
else
fprintf(tofile, format, *words.by_az);
words.by_az++;
i++;
}
}
}
static Word *get_the_rightest(Word *root)
{
if (root->rsibl)
return get_the_rightest(root->rsibl);
else
return root;
/*it's useless but GCC wants it to be*/
return NULL;
}
void free_words(Word *root)
{
if (root->lsibl)
free_words(root->lsibl);
if (root->rsibl)
free_words(root->rsibl);
free_word(root);
}
static inline void free_word(Word *record)
{
free(record->word);
free(record);
}
static inline char *wordcpy(char *word)
{
char *p;
p = malloc(strlen(word)+1);
if (p != NULL)
strcpy(p, word);
return p;
}