summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am17
-rw-r--r--src/Makefile.in434
-rw-r--r--src/confwin.c368
-rw-r--r--src/confwin.h25
-rw-r--r--src/dict.c109
-rw-r--r--src/dict.h36
-rw-r--r--src/dictwin.c403
-rw-r--r--src/dictwin.h25
-rw-r--r--src/engparser.c118
-rw-r--r--src/engparser.h53
-rw-r--r--src/main.c182
-rw-r--r--src/main.h52
-rw-r--r--src/mainwin.c815
-rw-r--r--src/mainwin.h31
-rw-r--r--src/srt.c145
-rw-r--r--src/srt.h26
-rw-r--r--src/word.c232
-rw-r--r--src/word.h53
18 files changed, 3124 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..38128ae
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,17 @@
+#Makefile.am for WordExtract project
+#Process this file with automake to produce Makefile.in
+
+wordextractdir = ../
+wordextract_PROGRAMS = wordextract
+wordextract_SOURCES = \
+ main.c main.h \
+ word.c word.h \
+ dict.c dict.h \
+ mainwin.c mainwin.h \
+ dictwin.c dictwin.h \
+ confwin.c confwin.h \
+ engparser.c engparser.h \
+ srt.c srt.h
+
+AM_CFLAGS = @GTK_CFLAGS@
+wordextract_LDADD = @GTK_LIBS@ \ No newline at end of file
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..425a6f8
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,434 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#Makefile.am for WordExtract project
+#Process this file with automake to produce Makefile.in
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+wordextract_PROGRAMS = wordextract$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(wordextractdir)"
+wordextractPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(wordextract_PROGRAMS)
+am_wordextract_OBJECTS = main.$(OBJEXT) word.$(OBJEXT) dict.$(OBJEXT) \
+ mainwin.$(OBJEXT) dictwin.$(OBJEXT) confwin.$(OBJEXT) \
+ engparser.$(OBJEXT) srt.$(OBJEXT)
+wordextract_OBJECTS = $(am_wordextract_OBJECTS)
+wordextract_DEPENDENCIES =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(wordextract_SOURCES)
+DIST_SOURCES = $(wordextract_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+wordextractdir = ../
+wordextract_SOURCES = \
+ main.c main.h \
+ word.c word.h \
+ dict.c dict.h \
+ mainwin.c mainwin.h \
+ dictwin.c dictwin.h \
+ confwin.c confwin.h \
+ engparser.c engparser.h \
+ srt.c srt.h
+
+AM_CFLAGS = @GTK_CFLAGS@
+wordextract_LDADD = @GTK_LIBS@
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-wordextractPROGRAMS: $(wordextract_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(wordextractdir)" || $(MKDIR_P) "$(DESTDIR)$(wordextractdir)"
+ @list='$(wordextract_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(wordextractPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(wordextractdir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(wordextractPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(wordextractdir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-wordextractPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(wordextract_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(wordextractdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(wordextractdir)/$$f"; \
+ done
+
+clean-wordextractPROGRAMS:
+ -test -z "$(wordextract_PROGRAMS)" || rm -f $(wordextract_PROGRAMS)
+wordextract$(EXEEXT): $(wordextract_OBJECTS) $(wordextract_DEPENDENCIES)
+ @rm -f wordextract$(EXEEXT)
+ $(LINK) $(wordextract_OBJECTS) $(wordextract_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/confwin.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dict.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dictwin.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/engparser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mainwin.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/word.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(wordextractdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-wordextractPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-wordextractPROGRAMS
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-wordextractPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-wordextractPROGRAMS ctags distclean distclean-compile \
+ distclean-generic distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip \
+ install-wordextractPROGRAMS installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
+ ps ps-am tags uninstall uninstall-am \
+ uninstall-wordextractPROGRAMS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/confwin.c b/src/confwin.c
new file mode 100644
index 0000000..1923329
--- /dev/null
+++ b/src/confwin.c
@@ -0,0 +1,368 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtk/gtk.h>
+#include "mainwin.h"
+#include "engparser.h"
+#include "main.h"
+
+static GtkWidget *conf_win;
+
+/*saving controls*/
+static GtkWidget *col_counter;
+static GtkWidget *field_counter;
+/*general parsing controls*/
+static GtkWidget *wcap_btn;
+static GtkWidget *lower_first_cap;
+/*quote controls*/
+static GtkWidget *wquot_btn; /*==excl_with_quoted_btn (here and below*/
+static GtkWidget *quoted_btn; /*'excl_' part of vatiable name is omitted)*/
+static GtkWidget *st_quote_btn;
+static GtkWidget *mid_quote_btn;
+static GtkWidget *after_quote_btn;
+static GtkWidget *end_quote_btn;
+/*hyphen controls*/
+static GtkWidget *whyph_btn;
+static GtkWidget *hyphened_btn;
+static GtkWidget *st_hyphen_btn;
+static GtkWidget *mid_hyphen_btn;
+static GtkWidget *after_hyphen_btn;
+static GtkWidget *end_hyphen_btn;
+
+static void ok_btn_click(GtkWidget *, gpointer);
+static void cancel_btn_click(GtkWidget *, gpointer);
+static void wquot_btn_click(GtkWidget *, gpointer);
+static void mid_quote_btn_click(GtkWidget *, gpointer);
+static void after_quote_btn_click(GtkWidget *, gpointer);
+static void whyph_btn_click(GtkWidget *, gpointer);
+static void mid_hyphen_btn_click(GtkWidget *, gpointer);
+static void after_hyphen_btn_click(GtkWidget *, gpointer);
+
+void create_conf_win()
+{
+ conf_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_size_request(conf_win, 440, 330);
+ gtk_window_set_title(GTK_WINDOW(conf_win), "WordExtract Preferences");
+ gtk_window_set_transient_for(GTK_WINDOW(conf_win), GTK_WINDOW(main_window));
+ gtk_window_set_position(GTK_WINDOW(conf_win), GTK_WIN_POS_CENTER_ON_PARENT);
+ gtk_window_set_modal(GTK_WINDOW(conf_win), TRUE);
+ gtk_window_set_skip_taskbar_hint(GTK_WINDOW(conf_win), TRUE);
+
+ GtkWidget *vbox = gtk_vbox_new(FALSE, 2);
+ gtk_container_add(GTK_CONTAINER(conf_win), vbox);
+ gtk_widget_show(vbox);
+
+ GtkWidget *tabs = gtk_notebook_new();
+ gtk_box_pack_start(GTK_BOX(vbox), tabs, TRUE, TRUE, 2);
+ /*'General' tab*/
+ GtkWidget *gen_label = gtk_label_new("General");
+ GtkWidget *gen_frame = gtk_frame_new(NULL);
+ gtk_container_set_border_width(GTK_CONTAINER(gen_frame), 5);
+ gtk_frame_set_shadow_type(GTK_FRAME(gen_frame), GTK_SHADOW_IN);
+ gtk_widget_show(gen_frame);
+
+ GtkWidget *gen_table = gtk_table_new(6, 12, TRUE);
+ gtk_container_set_border_width(GTK_CONTAINER(gen_table), 10);
+ gtk_container_add(GTK_CONTAINER(gen_frame), gen_table);
+ gtk_widget_show(gen_table);
+
+ GtkWidget *save_label = gtk_label_new("<b>Words saving options</b>");
+ gtk_label_set_use_markup(GTK_LABEL(save_label), TRUE);
+ gtk_table_attach_defaults(GTK_TABLE(gen_table), save_label, 0, 6, 0, 1);
+ gtk_misc_set_alignment(GTK_MISC(save_label), 0, 0.5);
+ gtk_widget_show(save_label);
+
+ GtkWidget *col_label = gtk_label_new("Columns: ");
+ gtk_misc_set_alignment(GTK_MISC(col_label), 0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(gen_table), col_label, 1, 4, 1, 2);
+ gtk_widget_show(col_label);
+
+ GtkObject *col_adjust = gtk_adjustment_new(save_user_words.columns, 1, 10, 1, 2, 0);
+ col_counter = gtk_spin_button_new(GTK_ADJUSTMENT(col_adjust), 0.5, 0);
+ gtk_widget_set_tooltip_text(col_counter, "Specify how many columns will be in the saved list of the words");
+ gtk_table_attach_defaults(GTK_TABLE(gen_table), col_counter, 5, 7, 1, 2);
+ gtk_widget_show(col_counter);
+
+ gboolean field_sens = (save_user_words.columns > 1) ? TRUE : FALSE;
+ GtkWidget *field_label = gtk_label_new("Field langth: ");
+ gtk_misc_set_alignment(GTK_MISC(field_label), 0, 0.5);
+ gtk_widget_set_sensitive(field_label, field_sens);
+ gtk_table_attach_defaults(GTK_TABLE(gen_table), field_label, 1, 4, 2, 3);
+ gtk_widget_show(field_label);
+
+ GtkObject *field_adjust = gtk_adjustment_new(save_user_words.col_width, 10, 100, 1, 10, 0);
+ field_counter = gtk_spin_button_new(GTK_ADJUSTMENT(field_adjust), 0.5, 0);
+ gtk_widget_set_tooltip_text(field_counter, "Specify length of one field (in symbols) in the saved list of the words");
+ gtk_widget_set_sensitive(field_counter, field_sens);
+ gtk_table_attach_defaults(GTK_TABLE(gen_table), field_counter, 5, 7, 2, 3);
+ gtk_widget_show(field_counter);
+ gtk_notebook_append_page(GTK_NOTEBOOK(tabs), gen_frame, gen_label);
+
+ /*'Analysing' tab*/
+ GtkWidget *analys_label = gtk_label_new("Analysing");
+ GtkWidget *analys_frame = gtk_frame_new(NULL);
+ gtk_container_set_border_width(GTK_CONTAINER(analys_frame), 5);
+ gtk_frame_set_shadow_type(GTK_FRAME(analys_frame), GTK_SHADOW_IN);
+ gtk_widget_show(analys_frame);
+
+ GtkWidget *analys_sc_win = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(analys_sc_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_container_add(GTK_CONTAINER(analys_frame), analys_sc_win);
+ gtk_widget_show(analys_sc_win);
+
+ GtkWidget *analys_table = gtk_table_new(17, 12, TRUE);
+ gtk_container_set_border_width(GTK_CONTAINER(analys_table), 10);
+ gtk_widget_set_size_request(analys_table, 390, 700);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(analys_sc_win), analys_table);
+ gtk_widget_show(analys_table);
+
+ GtkWidget *lang_label = gtk_label_new("Analyser language: ");
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), lang_label, 0, 4, 0, 1);
+ gtk_widget_show(lang_label);
+
+ GtkWidget *lang_box = gtk_combo_box_new_text();
+ gtk_combo_box_append_text(GTK_COMBO_BOX(lang_box), "English");
+ gtk_combo_box_set_active(GTK_COMBO_BOX(lang_box), 0);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), lang_box, 5, 9, 0, 1);
+ gtk_widget_set_tooltip_text(lang_box, "Language of the text you want to analyse");
+ gtk_widget_show(lang_box);
+
+ wcap_btn = gtk_check_button_new_with_label("Exclude words with capital letters");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wcap_btn), (gboolean) excl_w_capital);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), wcap_btn, 0, 12, 1, 2);
+ gtk_widget_show(wcap_btn);
+
+ lower_first_cap = gtk_check_button_new_with_label("Lower first capital in each sentence");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lower_first_cap), (gboolean) lower_first_capital);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), lower_first_cap, 0, 12, 2, 3);
+ gtk_widget_show(lower_first_cap);
+
+ GtkWidget *quote_label = gtk_label_new("<b>Quotes analysis</b>");
+ gtk_label_set_use_markup(GTK_LABEL(quote_label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(quote_label), 0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), quote_label, 0, 12, 3, 4);
+ gtk_widget_show(quote_label);
+
+ wquot_btn = gtk_check_button_new_with_label("Exclude words with quotes");
+ gboolean quotes = quote.excl_symbolled&&quote.excl_w_starting
+ &&quote.excl_w_middle&&quote.excl_w_ending;
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wquot_btn), quotes);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), wquot_btn, 1, 12, 4, 5);
+ g_signal_connect(G_OBJECT(wquot_btn), "clicked", G_CALLBACK(wquot_btn_click), NULL);
+ gtk_widget_show(wquot_btn);
+
+ quoted_btn = gtk_check_button_new_with_label("Exclude 'quoted' words");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(quoted_btn), quote.excl_symbolled);
+ gtk_widget_set_sensitive(quoted_btn, !quotes);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), quoted_btn, 2, 12, 5, 6);
+ gtk_widget_show(quoted_btn);
+
+ st_quote_btn = gtk_check_button_new_with_label("Exclude words with 'quote in the beginning");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(st_quote_btn), quote.excl_w_starting);
+ gtk_widget_set_sensitive(st_quote_btn, !quotes);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), st_quote_btn, 2, 12, 6, 7);
+ gtk_widget_show(st_quote_btn);
+
+ mid_quote_btn = gtk_check_button_new_with_label("Exclude words with quo'te in the middle");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mid_quote_btn), quote.excl_w_middle);
+ gtk_widget_set_sensitive(mid_quote_btn, !quotes&&!quote.excl_word_after_symb);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), mid_quote_btn, 2, 12, 7, 8);
+ g_signal_connect(G_OBJECT(mid_quote_btn), "clicked", G_CALLBACK(mid_quote_btn_click), NULL);
+ gtk_widget_show(mid_quote_btn);
+
+ after_quote_btn = gtk_check_button_new();
+ GtkWidget *after_quote_label = gtk_label_new("Exclude part of the word after quo<s>'te</s>");
+ gtk_label_set_use_markup(GTK_LABEL(after_quote_label), TRUE);
+ gtk_container_add(GTK_CONTAINER(after_quote_btn), after_quote_label);
+ gtk_widget_show(after_quote_label);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(after_quote_btn), quote.excl_word_after_symb);
+ gtk_widget_set_sensitive(after_quote_btn, !quotes&&!quote.excl_w_middle);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), after_quote_btn, 2, 12, 8, 9);
+ g_signal_connect(G_OBJECT(after_quote_btn), "clicked", G_CALLBACK(after_quote_btn_click), NULL);
+ gtk_widget_show(after_quote_btn);
+
+ end_quote_btn = gtk_check_button_new_with_label("Exclude words with quote' in the end");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(end_quote_btn), quote.excl_w_ending);
+ gtk_widget_set_sensitive(end_quote_btn, !quotes);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), end_quote_btn, 2, 12, 9, 10);
+ gtk_widget_show(end_quote_btn);
+
+ GtkWidget *hyphen_label = gtk_label_new("<b>Hyphen analysis</b>");
+ gtk_label_set_use_markup(GTK_LABEL(hyphen_label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(hyphen_label), 0, 0.5);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), hyphen_label, 0, 12, 10, 11);
+ gtk_widget_show(hyphen_label);
+
+ whyph_btn = gtk_check_button_new_with_label("Exclude words with hyphens");
+ gboolean hyphens = hyphen.excl_symbolled&&hyphen.excl_w_starting
+ &&hyphen.excl_w_middle&&hyphen.excl_w_ending;
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(whyph_btn), hyphens);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), whyph_btn, 1, 12, 11, 12);
+ g_signal_connect(G_OBJECT(whyph_btn), "clicked", G_CALLBACK(whyph_btn_click), NULL);
+ gtk_widget_show(whyph_btn);
+
+ hyphened_btn = gtk_check_button_new_with_label("Exclude -hyphened- words");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hyphened_btn), hyphen.excl_symbolled);
+ gtk_widget_set_sensitive(hyphened_btn, !hyphens);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), hyphened_btn, 2, 12, 12, 13);
+ gtk_widget_show(hyphened_btn);
+
+ st_hyphen_btn = gtk_check_button_new_with_label("Exclude words with -hyphen in the beginning");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(st_hyphen_btn), hyphen.excl_w_starting);
+ gtk_widget_set_sensitive(st_hyphen_btn, !hyphens);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), st_hyphen_btn, 2, 12, 13, 14);
+ gtk_widget_show(st_hyphen_btn);
+
+ mid_hyphen_btn = gtk_check_button_new_with_label("Exclude words with hy-phen in the middle");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mid_hyphen_btn), hyphen.excl_w_middle);
+ gtk_widget_set_sensitive(mid_hyphen_btn, !hyphens);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), mid_hyphen_btn, 2, 12, 14, 15);
+ g_signal_connect(G_OBJECT(mid_hyphen_btn), "clicked", G_CALLBACK(mid_hyphen_btn_click), NULL);
+ gtk_widget_show(mid_hyphen_btn);
+
+ after_hyphen_btn = gtk_check_button_new();
+ GtkWidget *after_hyphen_label = gtk_label_new("Exclude part of the word after hy<s>-phen</s>");
+ gtk_label_set_use_markup(GTK_LABEL(after_hyphen_label), TRUE);
+ gtk_container_add(GTK_CONTAINER(after_hyphen_btn), after_hyphen_label);
+ gtk_widget_show(after_hyphen_label);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(after_hyphen_btn), hyphen.excl_word_after_symb);
+ gtk_widget_set_sensitive(after_hyphen_btn, !hyphens&&!hyphen.excl_w_middle);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), after_hyphen_btn, 2, 12, 15, 16);
+ g_signal_connect(G_OBJECT(after_hyphen_btn), "clicked", G_CALLBACK(after_hyphen_btn_click), NULL);
+ gtk_widget_show(after_hyphen_btn);
+
+ end_hyphen_btn = gtk_check_button_new_with_label("Exclude words with hyphen- in the end");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(end_hyphen_btn), hyphen.excl_w_ending);
+ gtk_widget_set_sensitive(end_hyphen_btn, !hyphens);
+ gtk_table_attach_defaults(GTK_TABLE(analys_table), end_hyphen_btn, 2, 12, 16, 17);
+ gtk_widget_show(end_hyphen_btn);
+ gtk_notebook_append_page(GTK_NOTEBOOK(tabs), analys_frame, analys_label);
+ gtk_widget_show(tabs);
+
+ GtkWidget *hbox = gtk_hbox_new(FALSE, 2);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show(hbox);
+
+ GtkWidget *btn_hbox = gtk_hbox_new(TRUE, 2);
+ gtk_box_pack_end(GTK_BOX(hbox), btn_hbox, FALSE, FALSE, 0);
+ gtk_widget_show(btn_hbox);
+
+ GtkWidget *ok_btn = gtk_button_new_from_stock(GTK_STOCK_OK);
+ gtk_box_pack_end(GTK_BOX(btn_hbox), ok_btn, TRUE, TRUE, 0);
+ g_signal_connect(G_OBJECT(ok_btn), "clicked", G_CALLBACK(ok_btn_click), NULL);
+ gtk_widget_show(ok_btn);
+
+ GtkWidget *cancel_btn = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_box_pack_end(GTK_BOX(btn_hbox), cancel_btn, TRUE, TRUE, 0);
+ g_signal_connect(G_OBJECT(cancel_btn), "clicked", G_CALLBACK(cancel_btn_click), NULL);
+ gtk_widget_show(cancel_btn);
+
+ gtk_widget_show(conf_win);
+}
+
+static void ok_btn_click(GtkWidget *widget, gpointer data)
+{
+ save_user_words.columns = (int) gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(col_counter));
+ save_user_words.col_width = (int) gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(field_counter));
+ /*lang = */
+ excl_w_capital = (int) GTK_TOGGLE_BUTTON(wcap_btn)->active;
+ lower_first_capital = (int) GTK_TOGGLE_BUTTON(lower_first_cap)->active;
+ if (GTK_TOGGLE_BUTTON(wquot_btn)->active) {
+ quote.excl_symbolled = 1;
+ quote.excl_w_starting = 1;
+ quote.excl_w_middle = 1;
+ quote.excl_w_ending = 1;
+ } else {
+ quote.excl_symbolled = (int) GTK_TOGGLE_BUTTON(quoted_btn)->active;
+ quote.excl_w_starting = (int) GTK_TOGGLE_BUTTON(st_quote_btn)->active;
+ quote.excl_w_middle = (int) GTK_TOGGLE_BUTTON(mid_quote_btn)->active;
+ quote.excl_word_after_symb = (int) GTK_TOGGLE_BUTTON(after_quote_btn)->active;
+ quote.excl_w_ending = (int) GTK_TOGGLE_BUTTON(end_quote_btn)->active;
+ }
+ if (GTK_TOGGLE_BUTTON(whyph_btn)->active) {
+ hyphen.excl_symbolled = 1;
+ hyphen.excl_w_starting = 1;
+ hyphen.excl_w_middle = 1;
+ hyphen.excl_w_ending = 1;
+ } else {
+ hyphen.excl_symbolled = (int) GTK_TOGGLE_BUTTON(hyphened_btn)->active;
+ hyphen.excl_w_starting = (int) GTK_TOGGLE_BUTTON(st_hyphen_btn)->active;
+ hyphen.excl_w_middle = (int) GTK_TOGGLE_BUTTON(mid_hyphen_btn)->active;
+ hyphen.excl_word_after_symb = (int) GTK_TOGGLE_BUTTON(after_hyphen_btn)->active;
+ hyphen.excl_w_ending = (int) GTK_TOGGLE_BUTTON(end_hyphen_btn)->active;
+ }
+ write_config();
+ gtk_widget_destroy(conf_win);
+}
+
+static void cancel_btn_click(GtkWidget *widget, gpointer data)
+{
+ gtk_widget_destroy(conf_win);
+}
+
+static void wquot_btn_click(GtkWidget *button, gpointer data)
+{
+ gboolean state = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
+ gtk_widget_set_sensitive(quoted_btn, state);
+ gtk_widget_set_sensitive(st_quote_btn, state);
+ gtk_widget_set_sensitive(mid_quote_btn, state&&!GTK_TOGGLE_BUTTON(after_quote_btn)->active);
+ gtk_widget_set_sensitive(after_quote_btn, state&&!GTK_TOGGLE_BUTTON(mid_quote_btn)->active);
+ gtk_widget_set_sensitive(end_quote_btn, state);
+}
+
+static void mid_quote_btn_click(GtkWidget *button, gpointer data)
+{
+ gboolean state = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
+ gtk_widget_set_sensitive(after_quote_btn, state);
+}
+
+static void after_quote_btn_click(GtkWidget *button, gpointer data)
+{
+ gboolean state = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
+ gtk_widget_set_sensitive(mid_quote_btn, state);
+}
+
+static void whyph_btn_click(GtkWidget *button, gpointer data)
+{
+ gboolean state = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
+ gtk_widget_set_sensitive(hyphened_btn, state);
+ gtk_widget_set_sensitive(st_hyphen_btn, state);
+ gtk_widget_set_sensitive(mid_hyphen_btn, state&&!GTK_TOGGLE_BUTTON(after_hyphen_btn)->active);
+ gtk_widget_set_sensitive(after_hyphen_btn, state&&!GTK_TOGGLE_BUTTON(mid_hyphen_btn)->active);
+ gtk_widget_set_sensitive(end_hyphen_btn, state);
+}
+
+static void mid_hyphen_btn_click(GtkWidget *button, gpointer data)
+{
+ gboolean state = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
+ gtk_widget_set_sensitive(after_hyphen_btn, state);
+}
+
+static void after_hyphen_btn_click(GtkWidget *button, gpointer data)
+{
+ gboolean state = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
+ gtk_widget_set_sensitive(mid_hyphen_btn, state);
+}
+
+
+
+
+
+
+
diff --git a/src/confwin.h b/src/confwin.h
new file mode 100644
index 0000000..e1c0761
--- /dev/null
+++ b/src/confwin.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CONFWIN_H
+#define CONFWIN_H
+
+void create_conf_win();
+
+#endif /*CONFWIN_H*/
diff --git a/src/dict.c b/src/dict.c
new file mode 100644
index 0000000..5f48c1d
--- /dev/null
+++ b/src/dict.c
@@ -0,0 +1,109 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "dict.h"
+#include "main.h"
+
+Word *dict;
+SortedWords dict_words = {0, NULL};
+
+static void create_dict_file(char *path);
+
+Word *load_dict()
+{
+ FILE *fdict;
+ Word *root = NULL;
+ char word[WORDLENGTH] = {0};
+ int i;
+
+ if (!(fdict = fopen(dictfile, "r"))) {
+ perror(dictfile);
+ create_dict_file(optpath);
+ if (!(fdict = fopen(dictfile, "r"))) {
+ perror(dictfile);
+ exit(1);
+ }
+ }
+ while (!feof(fdict)) {
+ fgets(word, WORDLENGTH, fdict);
+ if (strcmp(word, "\0") == 0) /*to not process final blank line*/
+ break;
+ word[strlen(word)-1] = '\0';
+ root = add_word(root, word);
+ for (i = 0; i < WORDLENGTH; i++)
+ word[i] = 0;
+ }
+ fclose(fdict);
+ dict_words = get_sorted(root);
+ return root;
+}
+
+void save_dict(FILE *file, Word *root)
+{
+ if (root != NULL) {
+ fprintf(file, "%s\n", root->word);
+ save_dict(file, root->lsibl);
+ save_dict(file, root->rsibl);
+ }
+}
+
+int is_in_dict(char *word, Word *dic_rec)
+{
+ int cond;
+
+ if (dic_rec == NULL)
+ return NOT_IN_DICT;
+ else {
+ if ((cond = strcmp(word, dic_rec->word)) == 0)
+ return IN_DICT;
+ else if (cond > 0)
+ return is_in_dict(word, dic_rec->rsibl);
+ else
+ return is_in_dict(word, dic_rec->lsibl);
+ }
+}
+
+void create_dict_file(char *path)
+{
+ mode_t mode_0755 = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
+ struct stat st;
+ FILE *fdict;
+ char file[PATH_LENGTH] = {0};
+
+ if (stat(path, &st)) {
+ fprintf(stderr, "%s: Creating directory\n", path);
+ if (mkdir(path, mode_0755)) {
+ perror(path);
+ exit(1);
+ }
+ }
+ strcat(file, path);
+ strcat(file, DICT_FILE);
+ fprintf(stderr, "%s: Creating blank dictionary file\n", file);
+ if (!(fdict = fopen(file, "w"))) {
+ perror(file);
+ exit(1);
+ }
+ fclose(fdict);
+}
+
diff --git a/src/dict.h b/src/dict.h
new file mode 100644
index 0000000..eb4bc70
--- /dev/null
+++ b/src/dict.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DICTIONARY_H
+#define DICTIONARY_H
+
+#include "word.h"
+
+#define DICT_FILE "/dict"
+#define IN_DICT 1
+#define NOT_IN_DICT 0
+
+extern Word *dict;
+extern SortedWords dict_words;
+
+Word *load_dict();
+void save_dict(FILE *, Word *);
+int is_in_dict(char *, Word *);
+
+#endif /*DICT_H*/
diff --git a/src/dictwin.c b/src/dictwin.c
new file mode 100644
index 0000000..c2458f2
--- /dev/null
+++ b/src/dictwin.c
@@ -0,0 +1,403 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <stdlib.h>
+#include <string.h>
+#include "dictwin.h"
+#include "mainwin.h"
+#include "dict.h"
+
+enum {ICON_COL = 0, ICON_STR_COL, WORD_COL, N_COLUMNS};
+enum {WORD_ITEM = 0};
+
+static GtkWidget *dict_words_list;
+static GtkWidget *user_words_list;
+static GtkListStore *user_store_model;
+static GtkWidget *words_cnt_label;
+
+static void set_words_count();
+static void gtk_renderer_set_stock_icon(GtkTreeViewColumn *, GtkCellRenderer *, GtkTreeModel *, GtkTreeIter *, gpointer);
+static gboolean dict_words_popup_by_click(GtkWidget *, GdkEventButton *, gpointer);
+static gboolean dict_words_popup_by_keybd(GtkWidget *, gpointer);
+static void dict_words_popup(GtkWidget *widget, GdkEventButton *);
+static void remove_word_item_click(GtkWidget *, gpointer);
+static gboolean dict_words_list_key_press(GtkWidget *, GdkEventKey *, gpointer);
+static gboolean user_words_list_key_press(GtkWidget *, GdkEventKey *, gpointer);
+static void fill_dict_words(GtkListStore *, char **);
+static void add_btn_click(GtkWidget *, gpointer);
+static gboolean add_entry_key_press(GtkWidget *, GdkEventKey *, gpointer);
+static void cancel_btn_click(GtkWidget *, gpointer);
+static void ok_btn_click(GtkWidget *, gpointer);
+
+void create_dict_win()
+{
+ /*at first we refresh sorted list of words*/
+ free(dict_words.by_az);
+ dict_words = get_sorted(dict);
+
+ GtkWidget *dict_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_size_request(dict_win, 550, 410);
+ gtk_window_set_title(GTK_WINDOW(dict_win), "My Dictionary");
+ gtk_window_set_transient_for(GTK_WINDOW(dict_win), GTK_WINDOW(main_window));
+ gtk_window_set_position(GTK_WINDOW(dict_win), GTK_WIN_POS_CENTER_ON_PARENT);
+ gtk_window_set_modal(GTK_WINDOW(dict_win), TRUE);
+ gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dict_win), TRUE);
+
+ GtkWidget *vbox = gtk_vbox_new(FALSE, 2);
+ gtk_container_add(GTK_CONTAINER(dict_win), vbox);
+ gtk_widget_show(vbox);
+
+ GtkWidget *dict_hbox = gtk_hbox_new(TRUE, 2);
+ gtk_box_pack_start(GTK_BOX(vbox), dict_hbox, TRUE, TRUE, 2);
+ gtk_widget_show(dict_hbox);
+
+ /*dictionary panel*/
+ GtkWidget *dict_vbox = gtk_vbox_new(FALSE, 2);
+ gtk_box_pack_start(GTK_BOX(dict_hbox), dict_vbox, TRUE, TRUE, 0);
+ gtk_widget_show(dict_vbox);
+
+ GtkWidget *dict_label = gtk_label_new("Words in your dictionary: ");
+ gtk_box_pack_start(GTK_BOX(dict_vbox), dict_label, FALSE, FALSE, 0);
+ gtk_widget_show(dict_label);
+
+ GtkWidget *dict_sc = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(dict_sc), GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dict_sc), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start(GTK_BOX(dict_vbox), dict_sc, TRUE, TRUE, 0);
+ gtk_widget_show(dict_sc);
+
+ dict_words_list = gtk_tree_view_new();
+ gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(dict_words_list)), GTK_SELECTION_SINGLE);
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(dict_words_list), FALSE);
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(dict_words_list), TRUE);
+ gtk_container_add(GTK_CONTAINER(dict_sc), dict_words_list);
+ GtkListStore *store_model = gtk_list_store_new(1, G_TYPE_STRING);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(dict_words_list), GTK_TREE_MODEL(store_model));
+
+ GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
+ g_object_set(renderer, "editable", TRUE, NULL);
+ GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes("List Items", renderer, "text", WORD_ITEM, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(dict_words_list), column);
+ g_signal_connect(G_OBJECT(dict_words_list), "button-press-event", G_CALLBACK(dict_words_popup_by_click), NULL);
+ g_signal_connect(G_OBJECT(dict_words_list), "popup-menu", G_CALLBACK(dict_words_popup_by_keybd), NULL);
+ fill_dict_words(store_model, dict_words.by_az);
+
+ g_signal_connect(G_OBJECT(dict_words_list), "key-press-event", G_CALLBACK(dict_words_list_key_press), NULL);
+ gtk_widget_show(dict_words_list);
+
+ /*user words panel*/
+ GtkWidget *user_vbox = gtk_vbox_new(FALSE, 2);
+ gtk_box_pack_start(GTK_BOX(dict_hbox), user_vbox, TRUE, TRUE, 0);
+ gtk_widget_show(user_vbox);
+
+ GtkWidget *user_label = gtk_label_new("Changes to your dictionary: ");
+ gtk_box_pack_start(GTK_BOX(user_vbox), user_label, FALSE, FALSE, 0);
+ gtk_widget_show(user_label);
+
+ GtkWidget *user_sc = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(user_sc), GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(user_sc), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start(GTK_BOX(user_vbox), user_sc, TRUE, TRUE, 0);
+ gtk_widget_show(user_sc);
+
+ user_words_list = gtk_tree_view_new();
+ gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(user_words_list)), GTK_SELECTION_SINGLE);
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(user_words_list), FALSE);
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(user_words_list), TRUE);
+ user_store_model = gtk_list_store_new(N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(user_words_list), GTK_TREE_MODEL(user_store_model));
+ g_object_unref(user_store_model);
+
+ GtkTreeViewColumn *user_column = gtk_tree_view_column_new();
+ GtkCellRenderer *icon_renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start(user_column, icon_renderer, TRUE);
+ gtk_tree_view_column_set_attributes(user_column, icon_renderer, "pixbuf", ICON_COL, NULL);
+ gtk_tree_view_column_set_cell_data_func(user_column, icon_renderer, gtk_renderer_set_stock_icon, NULL, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(user_words_list), user_column);
+ /*second data fild is for icon stock id. so it doesn't need column*/
+ user_column = gtk_tree_view_column_new();
+ renderer = gtk_cell_renderer_text_new();
+ g_object_set(renderer, "editable", TRUE, NULL);
+ gtk_tree_view_column_pack_start(user_column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes(user_column, renderer, "text", WORD_COL, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(user_words_list), user_column);
+ gtk_container_add(GTK_CONTAINER(user_sc), user_words_list);
+
+ g_signal_connect(G_OBJECT(user_words_list), "key-press-event", G_CALLBACK(user_words_list_key_press), NULL);
+ gtk_widget_show(user_words_list);
+
+ GtkWidget *entry_hbox = gtk_hbox_new(FALSE, 2);
+ gtk_box_pack_start(GTK_BOX(user_vbox), entry_hbox, FALSE, FALSE, 0);
+ gtk_widget_show(entry_hbox);
+
+ GtkWidget *add_label = gtk_label_new("Add word: ");
+ gtk_box_pack_start(GTK_BOX(entry_hbox), add_label, FALSE, FALSE, 0);
+ gtk_widget_show(add_label);
+
+ GtkWidget *add_entry = gtk_entry_new_with_max_length(WORDLENGTH);
+ gtk_box_pack_start(GTK_BOX(entry_hbox), add_entry, FALSE, FALSE, 0);
+ g_signal_connect(G_OBJECT(add_entry), "activate", G_CALLBACK(add_btn_click), NULL);
+ g_signal_connect(G_OBJECT(add_entry), "key-press-event", G_CALLBACK(add_entry_key_press), (gpointer) user_words_list);
+ gtk_widget_show(add_entry);
+
+ GtkWidget *add_btn = gtk_button_new();
+ GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(add_btn), image);
+ gtk_widget_show(image);
+ gtk_box_pack_start(GTK_BOX(entry_hbox), add_btn, FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(add_btn), "Add word to the dictionary");
+ g_signal_connect(G_OBJECT(add_btn), "clicked", G_CALLBACK(add_btn_click), (gpointer) add_entry);
+ gtk_widget_show(add_btn);
+
+ GtkWidget *hbox = gtk_hbox_new(FALSE, 2);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
+ gtk_widget_show(hbox);
+
+ words_cnt_label = gtk_label_new("");
+ set_words_count();
+ gtk_box_pack_start(GTK_BOX(hbox), words_cnt_label, FALSE, FALSE, 0);
+ gtk_widget_show(words_cnt_label);
+
+ GtkWidget *btn_hbox = gtk_hbox_new(TRUE, 2);
+ gtk_box_pack_end(GTK_BOX(hbox), btn_hbox, FALSE, FALSE, 0);
+ gtk_widget_show(btn_hbox);
+
+ GtkWidget *cancel_btn = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_box_pack_end(GTK_BOX(btn_hbox), cancel_btn, TRUE, TRUE, 0);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(cancel_btn), "Discard changes and close the window");
+ g_signal_connect(G_OBJECT(cancel_btn), "clicked", G_CALLBACK(cancel_btn_click), (gpointer) dict_win);
+ gtk_widget_show(cancel_btn);
+
+ GtkWidget *ok_btn = gtk_button_new_from_stock(GTK_STOCK_OK);
+ gtk_box_pack_end(GTK_BOX(btn_hbox), ok_btn, TRUE, TRUE, 0);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(ok_btn), "Apply changes and close the window");
+ g_signal_connect(G_OBJECT(ok_btn), "clicked", G_CALLBACK(ok_btn_click), (gpointer) dict_win);
+ gtk_widget_show(ok_btn);
+
+ gtk_widget_show(dict_win);
+}
+
+static void fill_dict_words(GtkListStore *store, char **word_list)
+{
+ GtkTreeIter iter;
+ int i;
+
+ for (i = 0; i < dict_words.count; i++) {
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, WORD_ITEM, *word_list, -1);
+ word_list++;
+ }
+}
+
+static void set_words_count()
+{
+ char words_cnt_str[40] = {0};
+ sprintf(words_cnt_str, "<b> Words in your dictionary: %d</b>", dict_words.count);
+ gtk_label_set_text(GTK_LABEL(words_cnt_label), words_cnt_str);
+ gtk_label_set_use_markup(GTK_LABEL(words_cnt_label), TRUE);
+}
+
+static void gtk_renderer_set_stock_icon(GtkTreeViewColumn *column, GtkCellRenderer *renderer,
+ GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
+{
+ gchar *stock_id;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(model), iter, ICON_STR_COL, &stock_id, -1);
+ g_object_set(renderer, "stock-id", stock_id, NULL);
+}
+
+static gboolean dict_words_popup_by_click(GtkWidget *word_list, GdkEventButton *event, gpointer data)
+{
+ GtkTreePath *path;
+
+ if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(word_list));
+ if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), NULL, NULL)) {
+ if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(word_list), (gint) event->x,
+ (gint) event->y, &path, NULL, NULL, NULL)) {
+ gtk_tree_selection_unselect_all(selection);
+ gtk_tree_selection_select_path(selection, path);
+ dict_words_popup(GTK_WIDGET(word_list), event);
+ return TRUE;
+ }
+ }
+ }
+return FALSE;
+}
+
+static gboolean dict_words_popup_by_keybd(GtkWidget *word_list, gpointer data)
+{
+ dict_words_popup(word_list, NULL);
+ return TRUE;
+}
+
+static void dict_words_popup(GtkWidget *widget, GdkEventButton *event)
+{
+ GtkWidget *popup_menu = gtk_menu_new();
+ GtkWidget *remove_word_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_REMOVE, NULL);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(remove_word_item), "Remove this word from the dictionary");
+ g_signal_connect(G_OBJECT(remove_word_item), "activate", G_CALLBACK(remove_word_item_click), NULL);
+ gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), remove_word_item);
+ gtk_widget_show(remove_word_item);
+ gtk_widget_show(popup_menu);
+ gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL, NULL, NULL,
+ (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent*)event));
+}
+
+static void remove_word_item_click(GtkWidget *widget, gpointer data)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean valid = FALSE, remove = TRUE;
+ gchar *word;
+
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dict_words_list));
+ if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+ gtk_tree_model_get(model, &iter, WORD_ITEM, &word, -1);
+ valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(user_store_model), &iter);
+ gchar *cur_word;
+ while (valid) {
+ gtk_tree_model_get(GTK_TREE_MODEL(user_store_model), &iter, WORD_COL, &cur_word, -1);
+ if (!strcmp(word, cur_word)) {
+ remove = FALSE;
+ g_free(cur_word);
+ break;
+ }
+ valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(user_store_model), &iter);
+ }
+ if (remove) {
+ gtk_list_store_append(user_store_model, &iter);
+ gtk_list_store_set(user_store_model, &iter, ICON_STR_COL, "gtk-remove", WORD_COL, word, -1);
+ }
+ }
+}
+
+static gboolean dict_words_list_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ if ((event->type == GDK_KEY_PRESS)&&(event->keyval == GDK_Delete))
+ remove_word_item_click(widget, data);
+ return FALSE;
+}
+
+static gboolean user_words_list_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ GtkTreeIter iter;
+
+ if ((event->type == GDK_KEY_PRESS)&&(event->keyval == GDK_Delete)) {
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(user_words_list));
+ if (gtk_tree_selection_get_selected(selection, NULL, &iter)) {
+ gtk_list_store_remove(GTK_LIST_STORE(user_store_model), &iter);
+ }
+ }
+ return FALSE;
+}
+
+static void add_btn_click(GtkWidget *widget, gpointer add_entry)
+{
+ GtkTreeIter iter;
+ gpointer entry;
+ gboolean valid, add = FALSE;
+ gchar *word;
+
+ if (add_entry)
+ entry = add_entry;
+ else
+ entry = widget;
+ word = (gchar *) gtk_entry_get_text(GTK_ENTRY(entry));
+ add = strcmp(word, "")&&!is_in_dict(word, dict);
+
+ if (add) {
+ /*check whether word is already in 'words to add' list*/
+ valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(user_store_model), &iter);
+ gchar *cur_word;
+ while (valid) {
+ gtk_tree_model_get(GTK_TREE_MODEL(user_store_model), &iter, WORD_COL, &cur_word, -1);
+ if (!strcmp(word, cur_word)) {
+ add = FALSE;
+ g_free(cur_word);
+ break;
+ }
+ valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(user_store_model), &iter);
+ }
+ }
+ if (add) {
+ gtk_list_store_append(user_store_model, &iter);
+ gtk_list_store_set(user_store_model, &iter, ICON_STR_COL, "gtk-add", WORD_COL, word, -1);
+ gtk_entry_set_text(GTK_ENTRY(entry), "");
+ } else {
+ if (strcmp(word, "")) {
+ gtk_label_set_text(GTK_LABEL(words_cnt_label), "<b>This word is in your dictionary!</b>");
+ gtk_label_set_use_markup(GTK_LABEL(words_cnt_label), TRUE);
+ }
+ }
+}
+
+static gboolean add_entry_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ if (event->type == GDK_KEY_PRESS)
+ if ((event->length)||(event->keyval == GDK_BackSpace)||(event->keyval == GDK_Delete))
+ set_words_count();
+ return FALSE;
+}
+
+static void cancel_btn_click(GtkWidget *widget, gpointer dict_win)
+{
+ gtk_widget_destroy(GTK_WIDGET(dict_win));
+}
+
+static void ok_btn_click(GtkWidget *widget, gpointer dict_win)
+{
+ GtkTreeIter iter;
+ gboolean valid;
+ gchar *stock_id;
+ gchar *word;
+ FILE *fdict;
+
+ valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(user_store_model), &iter);
+ while (valid) {
+ gtk_tree_model_get(GTK_TREE_MODEL(user_store_model), &iter, ICON_STR_COL, &stock_id, -1);
+ if (!strcmp(stock_id, "gtk-add")) {
+ gtk_tree_model_get(GTK_TREE_MODEL(user_store_model), &iter, WORD_COL, &word, -1);
+ add_word(dict, word);
+ g_free(stock_id);
+ g_free(word);
+ }
+ if (!strcmp(stock_id, "gtk-remove")) {
+ gtk_tree_model_get(GTK_TREE_MODEL(user_store_model), &iter, WORD_COL, &word, -1);
+ del_word(&dict, word);
+ g_free(stock_id);
+ g_free(word);
+ }
+ valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(user_store_model), &iter);
+ }
+
+ if (!(fdict = fopen(dictfile, "w")))
+ perror(dictfile);
+ else {
+ save_dict(fdict, dict);
+ fclose(fdict);
+ }
+ free(dict_words.by_az);
+ dict_words = get_sorted(dict);
+ gtk_widget_destroy(GTK_WIDGET(dict_win));
+}
+
+
diff --git a/src/dictwin.h b/src/dictwin.h
new file mode 100644
index 0000000..2fe7ae2
--- /dev/null
+++ b/src/dictwin.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DICTWIN_H
+#define DICTWIN_H
+
+void create_dict_win();
+
+#endif /*DICTWIN_H*/
diff --git a/src/engparser.c b/src/engparser.c
new file mode 100644
index 0000000..af511e5
--- /dev/null
+++ b/src/engparser.c
@@ -0,0 +1,118 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "mainwin.h"
+#include "engparser.h"
+#include "word.h"
+#include "dict.h"
+
+int lower_first_capital = 1;
+int excl_w_capital = 1;
+Parseoptions hyphen = {'-', 0, 1, 0, 1, 0};
+Parseoptions quote = {'\'', 0, 1, 1, 0, 0};
+
+/* It deletes first and last symbol in the word*/
+static void del_first_n_last(char *word);
+
+int parseengphrase(char *phrase)
+{
+ extern Parseoptions hyphen;
+ extern Parseoptions quote;
+ char word[WORDLENGTH] = {0};
+ int sentence_start = 1;
+ int i, k;
+
+ add_sentence(phrase);
+ for (i = 0, k = 0; phrase[k] != '\0'; k++) {
+ if ((isalpha(phrase[k]))||(phrase[k] == '\'')||(phrase[k] == '-'))
+ {
+ word[i++] = phrase[k];
+ if ((lower_first_capital)&&(sentence_start)&&(phrase[k] != '\'')&&(phrase[k] != '-')) {
+ word[i-1] = tolower(word[i-1]);
+ sentence_start = 0;
+ }
+ }
+ else {
+ if ((*word != '\0')&&!parse_eng_word(word, quote)&&
+ !parse_eng_word(word, hyphen)&&!is_in_dict(word, dict))
+ words = add_word(words, word);
+ sentence_start = sentence_start||(phrase[k] == '.')||(phrase[k] == '!')||(phrase[k] == '?');
+ for (i = 0; i < WORDLENGTH; i++)
+ word[i] = 0;
+ i = 0;
+ }
+ }
+ return 0;
+}
+
+int parse_eng_word(char *word, Parseoptions opt)
+{
+ extern int excl_w_capital;
+ int ends = 0, sts = 0, mids = 0;
+ int symbolled = 0;
+ int capital = 0;
+ int wlength = 0;
+ int i;
+
+ wlength = strlen(word);
+ for (i = 0; word[i] != '\0'; i++) {
+ capital = capital||isupper(word[i]);
+ if (word[i] == opt.symbol) {
+ if (i == 0)
+ sts = 1;
+ else if (i == wlength-1)
+ ends = 1;
+ else
+ mids = 1;
+ }
+ if (mids&&opt.excl_word_after_symb&&!opt.excl_w_middle) {
+ word[i] = '\0';
+ break;
+ }
+ }
+ if (excl_w_capital&&capital)
+ return WORD_NOT_INCLUDED;
+ symbolled = sts&&ends;
+ if (symbolled)
+ del_first_n_last(word);
+ if (opt.excl_symbolled&&symbolled)
+ return WORD_NOT_INCLUDED;
+ if (opt.excl_w_starting&&sts&&!symbolled)
+ return WORD_NOT_INCLUDED;
+ if (opt.excl_w_middle&&mids)
+ return WORD_NOT_INCLUDED;
+ if (opt.excl_w_ending&&ends&&!symbolled)
+ return WORD_NOT_INCLUDED;
+ return WORD_INCLUDED;
+}
+
+static void del_first_n_last(char *word)
+{
+ int i, k;
+ int wlength;
+
+ wlength = strlen(word);
+ for (k = 0, i = 1; word[i] != '\''; i++, k++)
+ word[k] = word[i];
+ word[k] = '\0';
+}
+
diff --git a/src/engparser.h b/src/engparser.h
new file mode 100644
index 0000000..ca0a1b5
--- /dev/null
+++ b/src/engparser.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ENG_PARSER_H
+#define ENG_PARSER_H
+
+#define WORD_INCLUDED 0
+#define WORD_NOT_INCLUDED 1
+
+typedef struct {
+ char symbol;
+ int excl_symbolled;
+ int excl_w_starting;
+ int excl_w_middle;
+ int excl_w_ending;
+ int excl_word_after_symb;
+} Parseoptions;
+
+/* Parsing options */
+extern int excl_w_capital;
+extern int lower_first_capital;
+extern Parseoptions hyphen;
+extern Parseoptions quote;
+
+/*
+ * Recieves: line terminated by "\n\0"
+ *
+ * Words with "-" we'll be processed as a whole word
+ * And also we suppose that each sentence starts with capital letter
+ * and other words in the middle of the sentence which starts with
+ * capital letter is name (peoples, towns, I, etc...).
+ * Single quoted sentences are not allowed. It's gramatically incorrect
+ */
+int parseengphrase(char *);
+int parse_eng_word(char *word, Parseoptions opt);
+
+#endif /*ENG_PARSER_H*/
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..8ffced8
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,182 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "main.h"
+#include "mainwin.h"
+#include "dict.h"
+#include "engparser.h"
+
+Language lang;
+SaveOpt save_user_words = {2, 40};
+char optpath[PATH_LENGTH] = {0};
+char dictfile[PATH_LENGTH] = {0};
+char conffile[PATH_LENGTH] = {0};
+
+static void fill_vars();
+
+int main(int argc, char *argv[])
+{
+ FILE *fdict;
+
+ gtk_init(&argc, &argv);
+ fill_vars();
+ dict = load_dict();
+ lang = ENG;
+ create_main_window();
+ gtk_widget_show(main_window);
+ gtk_main();
+
+ /*termination*/
+ if (!(fdict = fopen(dictfile, "w")))
+ perror(dictfile);
+ else {
+ save_dict(fdict, dict);
+ fclose(fdict);
+ }
+ if (dict_words.by_az)
+ free(dict_words.by_az);
+ if (user_words.by_az)
+ free(user_words.by_az);
+ if (dict) {
+ if (dict->lsibl)
+ free_words(dict->lsibl);
+ if (dict->rsibl)
+ free_words(dict->rsibl);
+ free(dict->word);
+ }
+ return 0;
+}
+
+static void fill_vars()
+{
+ strcpy(optpath, getenv("HOME"));
+ strcat(optpath, OPT_FOLDER);
+ strcat(dictfile, optpath);
+ strcat(dictfile, DICT_FILE);
+ strcat(conffile, optpath);
+ strcat(conffile, CONF_FILE);
+ read_config();
+}
+
+void create_config(char *path)
+{
+ mode_t mode_0755 = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
+ struct stat st;
+ FILE *conf;
+ char file[PATH_LENGTH] = {0};
+
+ if (stat(path, &st)) {
+ fprintf(stderr, "%s: Creating directory\n", path);
+ if (mkdir(path, mode_0755)) {
+ perror(path);
+ exit(1);
+ }
+ }
+ strcat(file, path);
+ strcat(file, CONF_FILE);
+ fprintf(stderr, "%s: Creating configuration file\n", file);
+ if (!(conf = fopen(file, "w"))) {
+ perror(file);
+ exit(1);
+ }
+ fclose(conf);
+}
+
+void read_config()
+{
+ FILE *conf;
+
+ if (!(conf = fopen(conffile, "r"))) {
+ perror(conffile);
+ create_config(optpath);
+ write_config();
+ if (!(conf = fopen(dictfile, "r"))) {
+ perror(conffile);
+ exit(1);
+ }
+ } else {
+ char option[OPTION_LENGTH] = {0};
+ char svalue[OPTION_LENGTH] = {0};
+ while (fscanf(conf, "%s\t\t%s\n", option, svalue) != EOF) {
+ if (!strcmp(option, "columns")) {
+ save_user_words.columns = atoi(svalue);
+ } else if (!strcmp(option, "field")) {
+ save_user_words.col_width = atoi(svalue);
+ } else if (!strcmp(option, "language")) {
+ lang = atoi(svalue);
+ } else if (!strcmp(option, "exclude_with_capital")) {
+ excl_w_capital = atoi(svalue);
+ } else if (!strcmp(option, "lower_first_capital")) {
+ lower_first_capital = atoi(svalue);
+ } else if (!strcmp(option, "exclude_quoted")) {
+ quote.excl_symbolled = atoi(svalue);
+ } else if (!strcmp(option, "exclude_with_first_quote")) {
+ quote.excl_w_starting = atoi(svalue);
+ } else if (!strcmp(option, "exclude_with_middle_quote")) {
+ quote.excl_w_middle = atoi(svalue);
+ } else if (!strcmp(option, "exclude_part_after_quote")) {
+ quote.excl_word_after_symb = atoi(svalue);
+ } else if (!strcmp(option, "exclude_with_end_quote")) {
+ quote.excl_w_ending = atoi(svalue);
+ } else if (!strcmp(option, "exclude_hyphened")) {
+ hyphen.excl_symbolled = atoi(svalue);
+ } else if (!strcmp(option, "exclude_with_first_hyphen")) {
+ hyphen.excl_w_starting = atoi(svalue);
+ } else if (!strcmp(option, "exclude_with_middle_hyphen")) {
+ hyphen.excl_w_middle = atoi(svalue);
+ } else if (!strcmp(option, "exclude_part_after_hyphen")) {
+ hyphen.excl_word_after_symb = atoi(svalue);
+ } else if (!strcmp(option, "exclude_with_end_hyphen")) {
+ hyphen.excl_w_ending = atoi(svalue);
+ }
+ }
+ fclose(conf);
+ }
+}
+
+void write_config()
+{
+ FILE *conf;
+
+ if (!(conf = fopen(conffile, "w")))
+ perror(conffile);
+ else {
+ fprintf(conf, "%s\t\t%d\n", "columns", save_user_words.columns);
+ fprintf(conf, "%s\t\t%d\n", "field", save_user_words.col_width);
+ fprintf(conf, "%s\t\t%d\n", "language", lang);
+ fprintf(conf, "%s\t\t%d\n", "exclude_with_capital", excl_w_capital);
+ fprintf(conf, "%s\t\t%d\n", "lower_first_capital", lower_first_capital);
+ fprintf(conf, "%s\t\t%d\n", "exclude_quoted", quote.excl_symbolled);
+ fprintf(conf, "%s\t\t%d\n", "exclude_with_first_quote", quote.excl_w_starting);
+ fprintf(conf, "%s\t\t%d\n", "exclude_with_middle_quote", quote.excl_w_middle);
+ fprintf(conf, "%s\t\t%d\n", "exclude_part_after_quote", quote.excl_word_after_symb);
+ fprintf(conf, "%s\t\t%d\n", "exclude_with_end_quote", quote.excl_w_ending);
+ fprintf(conf, "%s\t\t%d\n", "exclude_hyphened", hyphen.excl_symbolled);
+ fprintf(conf, "%s\t\t%d\n", "exclude_with_first_hyphen", hyphen.excl_w_starting);
+ fprintf(conf, "%s\t\t%d\n", "exclude_with_middle_hyphen", hyphen.excl_w_middle);
+ fprintf(conf, "%s\t\t%d\n", "exclude_part_after_hyphen", hyphen.excl_word_after_symb);
+ fprintf(conf, "%s\t\t%d\n", "exclude_with_end_hyphen", hyphen.excl_w_ending);
+ fclose(conf);
+ }
+}
+
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..b2f8308
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#define PATH_LENGTH 50
+#define PROGNAME "wordextract"
+#define OPT_FOLDER "/.wordextract"
+#define CONF_FILE "/config"
+#define OPTION_LENGTH 30
+/* maximum subtitle line and phrase length
+ * it's not allocated dinamically 'cause it costs a lot of resources and
+ * it can't be more than mean human reading speed in a half of a minute
+ * it's about 100 letters + formatting
+ */
+#define MAXLINE 300
+#define MAXPHRASE 100
+
+typedef enum {ENG = 0} Language;
+typedef struct {
+ unsigned int columns;
+ unsigned int col_width;
+} SaveOpt;
+
+/*application settings*/
+extern Language lang;
+extern SaveOpt save_user_words;
+
+extern char optpath[PATH_LENGTH];
+extern char dictfile[PATH_LENGTH];
+
+void read_config();
+void write_config();
+
+#endif /*MAIN_H*/
diff --git a/src/mainwin.c b/src/mainwin.c
new file mode 100644
index 0000000..4cda3f0
--- /dev/null
+++ b/src/mainwin.c
@@ -0,0 +1,815 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gdk/gdkkeysyms.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <string.h>
+#include <ctype.h>
+#include "mainwin.h"
+#include "dictwin.h"
+#include "confwin.h"
+#include "main.h"
+#include "word.h"
+#include "dict.h"
+#include "srt.h"
+
+#define SEARCH_FORWARD 0
+#define SEARCH_BACKWARD 1
+#define ERR_READING_FILE "Could not open the file "
+#define ERR_SAVING_FILE "Could not save the file "
+#define ERR_MSG_CAPTION "Error"
+#define QUIT_MSG_CAPTION "Confirmation"
+#define QUIT_MSG_TEXT "Are you sure to exit?"
+
+enum {WORD_ITEM = 0, N_COLUMNS};
+
+GtkWidget *main_window;
+
+static GtkWidget *sentences_text;
+static GtkWidget *find_btn;
+static GtkWidget *prev_btn;
+static GtkWidget *next_btn;
+static GtkWidget *clear_btn;
+static GtkWidget *statusbar;
+/*list view variables*/
+static GtkWidget *word_list;
+static GtkListStore *store_model;
+/*widgets which should be disabled/enabled*/
+static GtkWidget *save_item;
+static GtkToolItem *save;
+static GtkWidget *find_label;
+static GtkWidget *find_entry;
+/*vars to control current word highlighting (green)*/
+static int current_highlighted_end;
+static int current_highlighted_start;
+/*statusbar context id*/
+static guint id, find_id;
+
+static void set_status_msg();
+static gint main_window_close(GtkWidget *, GdkEvent *, gpointer);
+static void main_window_destroy(GtkWidget *, gpointer);
+static void open_item_click(GtkWidget *, gpointer);
+static void save_words_item_click(GtkWidget *, gpointer);
+static void save_text_item_click(GtkWidget *, gpointer);
+static void quit_item_click(GtkWidget *, gpointer);
+static void dict_item_click(GtkWidget *, gpointer);
+static void pref_item_click(GtkWidget *, gpointer);
+static void about_item_click(GtkWidget *, gpointer);
+static gboolean popup_by_click(GtkWidget *, GdkEventButton *, gpointer);
+static gboolean popup_by_keybd(GtkWidget *, gpointer);
+static void word_list_popup(GtkWidget *, GdkEventButton *);
+static void show_sent_item_click(GtkWidget *, gpointer );
+static void add_to_dict_item_click(GtkWidget *, gpointer );
+static void fill_list(char **);
+static void change_search_navigation_state(gboolean);
+static gboolean find_entry_key_press(GtkWidget *, GdkEventKey *, gpointer);
+static void on_find_text_change(GtkWidget *, gpointer);
+static void find_prev_btn_click(GtkWidget *, gpointer);
+static void find_next_btn_click(GtkWidget *, gpointer);
+static void clear_btn_click(GtkWidget *, gpointer);
+static void search_sentences(const gchar *);
+static void set_find_text(gchar *);
+static void clear_search_tags();
+static gboolean gtk_text_iter_search_word(const GtkTextIter *, const gchar *,
+ GtkTextSearchFlags, GtkTextIter *,
+ GtkTextIter *, const GtkTextIter *, int);
+static void find_other(const gchar *, const int);
+
+void create_main_window()
+{
+ main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_size_request(main_window, 640, 480);
+ gtk_window_set_title(GTK_WINDOW(main_window), "WordExtract");
+ gtk_window_set_position(GTK_WINDOW(main_window), GTK_WIN_POS_CENTER);
+ g_signal_connect(G_OBJECT(main_window), "delete_event", G_CALLBACK(main_window_close), (gpointer) main_window);
+ g_signal_connect(G_OBJECT(main_window), "destroy", G_CALLBACK(main_window_destroy), NULL);
+
+ GtkWidget *vbox = gtk_vbox_new(FALSE, 2);
+ gtk_widget_show(vbox);
+ gtk_container_add(GTK_CONTAINER(main_window), vbox);
+
+ GtkWidget *menu_bar = gtk_menu_bar_new();
+ GtkWidget *sep_item = gtk_separator_menu_item_new();
+ GtkWidget *file_menu = gtk_menu_new();
+ GtkWidget *file_item = gtk_menu_item_new_with_mnemonic("_File");
+
+ GtkWidget *open_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(open_item), "Open file to analyse");
+ g_signal_connect(G_OBJECT(open_item), "activate", G_CALLBACK(open_item_click), NULL);
+ save_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_SAVE_AS, NULL);
+ gtk_widget_set_sensitive(GTK_WIDGET(save_item), FALSE);
+ GtkWidget *save_menu = gtk_menu_new();
+ GtkWidget *save_words_img = gtk_image_new_from_stock(GTK_STOCK_SAVE_AS, GTK_ICON_SIZE_MENU);
+ GtkWidget *save_words_item = gtk_image_menu_item_new_with_label("Words");
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(save_words_item), save_words_img);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(save_words_item), "Save list of words to file");
+ g_signal_connect(G_OBJECT(save_words_item), "activate", G_CALLBACK(save_words_item_click), NULL);
+ GtkWidget *save_text_img = gtk_image_new_from_stock(GTK_STOCK_SAVE_AS, GTK_ICON_SIZE_MENU);
+ GtkWidget *save_text_item = gtk_image_menu_item_new_with_label("Text");
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(save_text_item), save_text_img);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(save_text_item), "Save text from which words were picked up");
+ g_signal_connect(G_OBJECT(save_text_item), "activate", G_CALLBACK(save_text_item_click), NULL);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(save_item), save_menu);
+ gtk_menu_shell_append(GTK_MENU_SHELL(save_menu), save_words_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(save_menu), save_text_item);
+ GtkWidget *quit_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(quit_item), "Close the program");
+ g_signal_connect(G_OBJECT(quit_item), "activate", G_CALLBACK(quit_item_click), NULL);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_item), file_menu);
+ gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), open_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), sep_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), quit_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), file_item);
+ gtk_widget_show_all(file_item);
+
+ GtkWidget *edit_menu = gtk_menu_new();
+ GtkWidget *edit_item = gtk_menu_item_new_with_mnemonic("_Edit");
+ GtkWidget *dict_item = gtk_image_menu_item_new_with_label("Dictionary");
+ gtk_widget_set_tooltip_text(GTK_WIDGET(dict_item), "View and edit your dictionary");
+ GtkWidget *edit_img = gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(dict_item), edit_img);
+ g_signal_connect(G_OBJECT(dict_item), "activate", G_CALLBACK(dict_item_click), NULL);
+ GtkWidget *pref_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES, NULL);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(pref_item), "Change application settings");
+ g_signal_connect(G_OBJECT(pref_item), "activate", G_CALLBACK(pref_item_click), NULL);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(edit_item), edit_menu);
+ gtk_menu_shell_append(GTK_MENU_SHELL(edit_menu), dict_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(edit_menu), pref_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), edit_item);
+ gtk_widget_show_all(edit_item);
+
+ GtkWidget *help_menu = gtk_menu_new();
+ GtkWidget *help_item = gtk_menu_item_new_with_mnemonic("_Help");
+ GtkWidget *about_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, NULL);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(about_item), "About the program");
+ g_signal_connect(G_OBJECT(about_item), "activate", G_CALLBACK(about_item_click), NULL);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(help_item), help_menu);
+ gtk_menu_shell_append(GTK_MENU_SHELL(help_menu), about_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), help_item);
+ gtk_widget_show_all(help_item);
+
+ gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
+ gtk_widget_show(menu_bar);
+
+ GtkWidget *toolbar = gtk_toolbar_new();
+ gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
+ GtkToolItem *open = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(open), "Open file to analyse");
+ g_signal_connect(G_OBJECT(open), "clicked", G_CALLBACK(open_item_click), NULL);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), open, -1);
+ save = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
+ gtk_widget_set_has_tooltip(GTK_WIDGET(save), FALSE);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(save), "Save list of words to file");
+ gtk_widget_set_sensitive(GTK_WIDGET(save), FALSE);
+ g_signal_connect(G_OBJECT(save), "clicked", G_CALLBACK(save_words_item_click), NULL);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), save, -1);
+ GtkToolItem *tool_sep1 = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_sep1, -1);
+ GtkToolItem *dict = gtk_tool_button_new_from_stock(GTK_STOCK_EDIT);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(dict), "View and edit your dictionary");
+ g_signal_connect(G_OBJECT(dict), "clicked", G_CALLBACK(dict_item_click), NULL);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), dict, -1);
+ GtkToolItem *tool_sep2 = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_sep2, -1);
+ GtkToolItem *quit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(quit), "Close the program");
+ g_signal_connect(G_OBJECT(quit), "clicked", G_CALLBACK(quit_item_click), NULL);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), quit, -1);
+ gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 2);
+ gtk_widget_show_all(toolbar);
+
+ GtkWidget *hpaned = gtk_hpaned_new();
+ gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0);
+ gtk_paned_set_position(GTK_PANED(hpaned), 200);
+ gtk_widget_show(hpaned);
+
+ GtkWidget *word_sc_win = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(word_sc_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_paned_add1(GTK_PANED(hpaned), word_sc_win);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(word_sc_win), GTK_SHADOW_IN);
+ gtk_widget_show(word_sc_win);
+
+ word_list = gtk_tree_view_new();
+ gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(word_list)), GTK_SELECTION_SINGLE);
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(word_list), FALSE);
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(word_list), TRUE);
+ g_signal_connect(G_OBJECT(word_list), "button-press-event", G_CALLBACK(popup_by_click), NULL);
+ g_signal_connect(G_OBJECT(word_list), "popup-menu", G_CALLBACK(popup_by_keybd), NULL);
+ store_model = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(word_list), GTK_TREE_MODEL(store_model));
+ g_object_unref(store_model);
+ GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
+ g_object_set(renderer, "editable", TRUE, NULL);
+ GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes("List Items", renderer, "text", WORD_ITEM, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(word_list), column);
+ gtk_container_add(GTK_CONTAINER(word_sc_win), word_list);
+ gtk_widget_show(word_list);
+
+ GtkWidget *text_vbox = gtk_vbox_new(FALSE, 0);
+ gtk_paned_add2(GTK_PANED(hpaned), text_vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(text_vbox), 2);
+ gtk_widget_show(text_vbox);
+
+ GtkWidget *sentences_sc_win = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sentences_sc_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start(GTK_BOX(text_vbox), sentences_sc_win, TRUE, TRUE, 0);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sentences_sc_win), GTK_SHADOW_IN);
+ gtk_widget_show(sentences_sc_win);
+
+ sentences_text = gtk_text_view_new();
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(sentences_text));
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(sentences_text), FALSE);
+ gtk_text_buffer_create_tag(buffer, "yellow-bg", "background", "yellow", NULL);
+ gtk_text_buffer_create_tag(buffer, "green-bg", "background", "green", NULL);
+ gtk_container_add(GTK_CONTAINER(sentences_sc_win), sentences_text);
+ gtk_widget_show(sentences_text);
+
+ GtkWidget *text_hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_end(GTK_BOX(text_vbox), text_hbox, FALSE, FALSE, 0);
+ gtk_widget_show(text_hbox);
+
+ find_label = gtk_label_new("Find: ");
+ gtk_box_pack_start(GTK_BOX(text_hbox), find_label, FALSE, FALSE, 0);
+ gtk_widget_set_sensitive(GTK_WIDGET(find_label), FALSE);
+ gtk_widget_show(find_label);
+
+ find_entry = gtk_entry_new_with_max_length(WORDLENGTH);
+ gtk_box_pack_start(GTK_BOX(text_hbox), find_entry, FALSE, FALSE, 0);
+ gtk_widget_set_sensitive(GTK_WIDGET(find_entry), FALSE);
+ g_signal_connect(G_OBJECT(find_entry), "activate", G_CALLBACK(on_find_text_change), NULL);
+ g_signal_connect(G_OBJECT(find_entry), "key-press-event", G_CALLBACK(find_entry_key_press), NULL);
+ gtk_widget_show(find_entry);
+
+ find_btn = gtk_button_new();
+ GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(find_btn), image);
+ gtk_widget_show(image);
+ gtk_box_pack_start(GTK_BOX(text_hbox), find_btn, FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(find_btn), "Find word");
+ gtk_widget_set_sensitive(GTK_WIDGET(find_btn), FALSE);
+ g_signal_connect(G_OBJECT(find_btn), "clicked", G_CALLBACK(on_find_text_change), NULL);
+ gtk_widget_show(find_btn);
+
+ prev_btn = gtk_button_new();
+ image = gtk_image_new_from_stock(GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(prev_btn), image);
+ gtk_widget_show(image);
+ gtk_box_pack_start(GTK_BOX(text_hbox), prev_btn, FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(prev_btn), "Previous sentence");
+ gtk_widget_set_sensitive(GTK_WIDGET(prev_btn), FALSE);
+ g_signal_connect(G_OBJECT(prev_btn), "clicked", G_CALLBACK(find_prev_btn_click), (gpointer) find_entry);
+ gtk_widget_show(prev_btn);
+
+ next_btn = gtk_button_new();
+ image = gtk_image_new_from_stock(GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(next_btn), image);
+ gtk_widget_show(image);
+ gtk_box_pack_start(GTK_BOX(text_hbox), next_btn, FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(next_btn), "Next sentence");
+ gtk_widget_set_sensitive(GTK_WIDGET(next_btn), FALSE);
+ g_signal_connect(G_OBJECT(next_btn), "clicked", G_CALLBACK(find_next_btn_click), (gpointer) find_entry);
+ gtk_widget_show(next_btn);
+
+ clear_btn = gtk_button_new();
+ image = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(clear_btn), image);
+ gtk_widget_show(image);
+ gtk_box_pack_start(GTK_BOX(text_hbox), clear_btn, FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(clear_btn), "Cleanup highlighting");
+ gtk_widget_set_sensitive(GTK_WIDGET(clear_btn), FALSE);
+ g_signal_connect(G_OBJECT(clear_btn), "clicked", G_CALLBACK(clear_btn_click), (gpointer) find_entry);
+ gtk_widget_show(clear_btn);
+
+ statusbar = gtk_statusbar_new();
+ gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
+ id = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "main_context");
+ find_id = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "find_context");
+ gtk_statusbar_push(GTK_STATUSBAR(statusbar), id, "Open file to pick up words from it...");
+ gtk_widget_show(statusbar);
+}
+
+static void set_status_msg()
+{
+ char words_cnt_str[40] = {0};
+ sprintf(words_cnt_str, "<b> Words in your dictionary: %d</b>", dict_words.count);
+ gtk_statusbar_pop(GTK_STATUSBAR(statusbar), find_id);
+}
+
+static gint main_window_close(GtkWidget *widget, GdkEvent *event, gpointer main_window)
+{
+ gint response = TRUE;
+
+ GtkWidget *dialog = gtk_message_dialog_new(main_window, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, QUIT_MSG_TEXT);
+ gtk_window_set_title(GTK_WINDOW(dialog), QUIT_MSG_CAPTION);
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES)
+ response = FALSE;
+ gtk_widget_destroy(dialog);
+
+ return response;
+}
+
+static void main_window_destroy(GtkWidget *widget, gpointer data)
+{
+ gtk_main_quit();
+}
+
+static void open_item_click(GtkWidget *widget, gpointer data)
+{
+ char *filename;
+ char *errstr;
+ FILE *subtitle;
+
+ GtkFileFilter *filter = gtk_file_filter_new();
+ gtk_file_filter_add_mime_type(filter, "application/x-subrip");
+ gtk_file_filter_set_name(filter, "SubRip subtitles (*srt)");
+ GtkWidget *filedialog = gtk_file_chooser_dialog_new("Open File for analysing",
+ GTK_WINDOW(main_window), GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN,
+ GTK_RESPONSE_ACCEPT, NULL);
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filedialog), filter);
+ if (gtk_dialog_run(GTK_DIALOG(filedialog)) == GTK_RESPONSE_ACCEPT) {
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filedialog));
+ if (!(subtitle = fopen(filename, "r"))) {
+ gtk_widget_destroy(filedialog);
+ errstr = malloc(strlen(filename) + strlen(ERR_READING_FILE));
+ strcpy(errstr, ERR_READING_FILE);
+ strcat(errstr, filename);
+ GtkWidget *errmsg = gtk_message_dialog_new(GTK_WINDOW(main_window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, errstr);
+ gtk_window_set_title(GTK_WINDOW(errmsg), ERR_MSG_CAPTION);
+ gtk_dialog_run(GTK_DIALOG(errmsg));
+ gtk_widget_destroy(errmsg);
+ free(errstr);
+ return ;
+ }
+ if (words != NULL) {
+ free(user_words.by_az);
+ free_words(words);
+ words = NULL;
+ gtk_list_store_clear(store_model);
+ clear_sentences();
+ } else {
+ gtk_widget_set_sensitive(GTK_WIDGET(find_label), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(find_entry), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(find_btn), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(save_item), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(save), TRUE);
+ }
+ process_srt(subtitle);
+ user_words = get_sorted(words);
+ fill_list(user_words.by_az);
+ fclose(subtitle);
+ gchar *file = malloc(strlen(filename)+1);
+ file = basename(filename);
+ gchar *status_msg = malloc(strlen(file)+40);
+ sprintf(status_msg, "%d words were picked up from '%s'", user_words.count, file);
+ gtk_statusbar_pop(GTK_STATUSBAR(statusbar), id);
+ gtk_statusbar_push(GTK_STATUSBAR(statusbar), id, status_msg);
+ }
+ gtk_widget_destroy(filedialog);
+}
+
+static void save_words_item_click(GtkWidget *widget, gpointer data)
+{
+ FILE *savefile;
+ gchar *filename;
+ gchar *errstr;
+
+ GtkWidget *filedialog = gtk_file_chooser_dialog_new("Save list of words as...",
+ GTK_WINDOW(main_window), GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE,
+ GTK_RESPONSE_ACCEPT, NULL);
+ if (gtk_dialog_run(GTK_DIALOG(filedialog)) == GTK_RESPONSE_ACCEPT) {
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filedialog));
+ if (!(savefile = fopen(filename, "w"))) {
+ gtk_widget_destroy(filedialog);
+ errstr = malloc(strlen(filename) + strlen(ERR_SAVING_FILE));
+ strcpy(errstr, ERR_SAVING_FILE);
+ strcat(errstr, filename);
+ GtkWidget *errmsg = gtk_message_dialog_new(GTK_WINDOW(main_window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, errstr);
+ gtk_window_set_title(GTK_WINDOW(errmsg), ERR_MSG_CAPTION);
+ gtk_dialog_run(GTK_DIALOG(errmsg));
+ gtk_widget_destroy(errmsg);
+ free(errstr);
+ return ;
+ }
+ save_words(savefile, user_words, save_user_words);
+ fclose(savefile);
+ }
+ gtk_widget_destroy(filedialog);
+}
+
+static void save_text_item_click(GtkWidget *widget, gpointer data)
+{
+ FILE *savefile;
+ gchar *filename;
+ gchar *errstr;
+ gchar *text;
+
+ GtkWidget *filedialog = gtk_file_chooser_dialog_new("Save text as...",
+ GTK_WINDOW(main_window), GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE,
+ GTK_RESPONSE_ACCEPT, NULL);
+ if (gtk_dialog_run(GTK_DIALOG(filedialog)) == GTK_RESPONSE_ACCEPT) {
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filedialog));
+ if (!(savefile = fopen(filename, "w"))) {
+ gtk_widget_destroy(filedialog);
+ errstr = malloc(strlen(filename) + strlen(ERR_SAVING_FILE));
+ strcpy(errstr, ERR_SAVING_FILE);
+ strcat(errstr, filename);
+ GtkWidget *errmsg = gtk_message_dialog_new(GTK_WINDOW(main_window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, errstr);
+ gtk_window_set_title(GTK_WINDOW(errmsg), ERR_MSG_CAPTION);
+ gtk_dialog_run(GTK_DIALOG(errmsg));
+ gtk_widget_destroy(errmsg);
+ return ;
+ }
+ GtkTextIter start, end;
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(sentences_text));
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ fprintf(savefile, text);
+ fclose(savefile);
+ }
+ gtk_widget_destroy(filedialog);
+}
+
+static void quit_item_click(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(main_window), GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, QUIT_MSG_TEXT);
+ gtk_window_set_title(GTK_WINDOW(dialog), QUIT_MSG_CAPTION);
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES) {
+ gtk_widget_destroy(dialog);
+ gtk_main_quit();
+ }
+ else
+ gtk_widget_destroy(dialog);
+}
+
+static void dict_item_click(GtkWidget *widget, gpointer data)
+{
+ create_dict_win();
+}
+
+static void pref_item_click(GtkWidget *widget, gpointer data)
+{
+ create_conf_win();
+}
+
+static void about_item_click(GtkWidget *widget, gpointer data)
+{
+ const gchar comment[] = {"WordExtract is a subtitle parser\n which shows all unique words\n from files."};
+ const gchar copyright[] = {"Copyright \xc2\xa9 2009 by Borisov Alexandr"};
+ const gchar gplv3[] = {"WordExtract is free software: you can\n"
+ "redistribute it and/or modify it under the\n"
+ "terms of the GNU General Public License as\n"
+ "published by the Free Software Foundation,\n"
+ "either version 3 of the License, or (at your\n"
+ "option) any later version.\n\n"
+ "WordExtract is distributed in the hope that\n"
+ "it will be useful, but WITHOUT ANY WARRANTY;\n"
+ "without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR\n"
+ "PURPOSE. See the GNU General Public License\n"
+ "for more details.\n\n"
+ "You should have received a copy of the GNU\n"
+ "General Public License along with WordExtract.\n"
+ "If not, see <http://www.gnu.org/licenses/>."};
+ const gchar *authors[] = {"Borisov Alexandr aka b0ric", NULL};
+
+ gtk_show_about_dialog(GTK_WINDOW(main_window), "name", "WordExtract",
+ "version", "v0.2",
+ "website", "http://null.net",
+ "comments", comment,
+ "copyright", copyright,
+ "license", gplv3,
+ "authors", authors,
+ "documenters", NULL,
+ "translator-credits", NULL,
+ "logo", NULL, NULL);
+}
+
+static gboolean popup_by_click(GtkWidget *word_list, GdkEventButton *event, gpointer data)
+{
+ GtkTreePath *path;
+
+ if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(word_list));
+ if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), NULL, NULL)) {
+ if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(word_list), (gint) event->x,
+ (gint) event->y, &path, NULL, NULL, NULL)) {
+ gtk_tree_selection_unselect_all(selection);
+ gtk_tree_selection_select_path(selection, path);
+ word_list_popup(GTK_WIDGET(word_list), event);
+ return TRUE;
+ }
+ }
+ }
+return FALSE;
+}
+
+static gboolean popup_by_keybd(GtkWidget *word_list, gpointer data)
+{
+ word_list_popup(word_list, NULL);
+ return TRUE;
+}
+
+static void word_list_popup(GtkWidget *widget, GdkEventButton *event)
+{
+ GtkWidget *popup_menu = gtk_menu_new();
+ GtkWidget *show_sent_item = gtk_image_menu_item_new_with_label("Show Sentence");
+ gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), show_sent_item);
+ gtk_widget_show(show_sent_item);
+ g_signal_connect(G_OBJECT(show_sent_item), "activate", G_CALLBACK(show_sent_item_click), NULL);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(show_sent_item), "Show sentenses word appears in");
+ GtkWidget *find_image = gtk_image_new_from_stock("gtk-find", GTK_ICON_SIZE_MENU);
+ gtk_widget_show(find_image);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(show_sent_item), find_image);
+ GtkWidget *add_to_dict_item = gtk_image_menu_item_new_with_label("Add To Dictionary");
+ gtk_widget_show(add_to_dict_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), add_to_dict_item);
+ g_signal_connect(add_to_dict_item, "activate", G_CALLBACK(add_to_dict_item_click), NULL);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(add_to_dict_item), "Add word to my dictionary");
+ GtkWidget *add_image = gtk_image_new_from_stock("gtk-add", GTK_ICON_SIZE_MENU);
+ gtk_widget_show(add_image);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(add_to_dict_item), add_image);
+ gtk_widget_show(popup_menu);
+ gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL, NULL, NULL,
+ (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent*)event));
+}
+
+static void show_sent_item_click(GtkWidget *widget, gpointer data)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gchar *word;
+
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(word_list));
+ if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+ gtk_tree_model_get(model, &iter, 0, &word, -1);
+ set_find_text(word);
+ change_search_navigation_state(TRUE);
+ search_sentences(word);
+ g_free(word);
+ }
+}
+
+static void add_to_dict_item_click(GtkWidget *widget, gpointer data)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gchar *word;
+
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(word_list));
+ if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+ gtk_tree_model_get(model, &iter, 0, &word, -1);
+ add_word(dict, word);
+ g_free(word);
+ }
+}
+
+static void fill_list(char **word_list)
+{
+ GtkTreeIter iter;
+ int cnt, i;
+
+ cnt = get_words_count(words);
+ for (i = 0; i < cnt; i++) {
+ gtk_list_store_append(store_model, &iter);
+ gtk_list_store_set(store_model, &iter, WORD_ITEM, *word_list, -1);
+ word_list++;
+ }
+}
+
+static void change_search_navigation_state(gboolean state)
+{
+ gtk_widget_set_sensitive(GTK_WIDGET(prev_btn), state);
+ gtk_widget_set_sensitive(GTK_WIDGET(next_btn), state);
+ gtk_widget_set_sensitive(GTK_WIDGET(clear_btn), state);
+}
+
+void add_sentence(char *sentence)
+{
+ GtkTextIter iter;
+
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(sentences_text));
+ gtk_text_buffer_get_end_iter(buffer, &iter);
+ gtk_text_buffer_insert(buffer, &iter, (gchar*) sentence, -1);
+}
+
+static gboolean find_entry_key_press(GtkWidget *entry, GdkEventKey *event, gpointer data)
+{
+ if (event->type == GDK_KEY_PRESS)
+ if ((event->length)||(event->keyval == GDK_BackSpace)||(event->keyval == GDK_Delete))
+ set_status_msg();
+ return FALSE;
+}
+
+static void on_find_text_change(GtkWidget *widget, gpointer data)
+{
+ const gchar *find_text;
+
+ find_text = gtk_entry_get_text(GTK_ENTRY(find_entry));
+ change_search_navigation_state(strcmp(find_text, ""));
+ if (strcmp(find_text, ""))
+ search_sentences(find_text);
+}
+
+static void find_next_btn_click(GtkWidget *widget, gpointer entry)
+{
+ const gchar *find_text = NULL;
+
+ find_text = gtk_entry_get_text(GTK_ENTRY(entry));
+ find_other(find_text, SEARCH_FORWARD);
+}
+
+static void find_prev_btn_click(GtkWidget *widget, gpointer entry)
+{
+ const gchar *find_text = NULL;
+
+ find_text = gtk_entry_get_text(GTK_ENTRY(entry));
+ find_other(find_text, SEARCH_BACKWARD);
+}
+
+static void clear_btn_click(GtkWidget *widget, gpointer data)
+{
+ clear_search_tags();
+ gtk_entry_set_text(GTK_ENTRY(find_entry), "");
+ set_status_msg();
+ change_search_navigation_state(FALSE);
+}
+
+void clear_sentences()
+{
+ GtkTextBuffer *buffer;
+ gchar text[] = "\0";
+
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(sentences_text));
+ gtk_text_buffer_set_text(buffer, text, -1);
+}
+
+static void search_sentences(const gchar *word)
+{
+ GtkTextIter find_start, find_end;
+ GtkTextIter match_start, match_end;
+ int offset, cnt = 0;
+
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(sentences_text));
+ gtk_text_buffer_get_start_iter(buffer, &find_start);
+ gtk_text_buffer_get_end_iter(buffer, &find_end);
+ gtk_text_buffer_remove_tag_by_name(buffer, "green-bg", &find_start, &find_end);
+ gtk_text_buffer_remove_tag_by_name(buffer, "yellow-bg", &find_start, &find_end);
+ while (gtk_text_iter_search_word(&find_start, word, GTK_TEXT_SEARCH_TEXT_ONLY|
+ GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start,
+ &match_end, NULL, SEARCH_FORWARD)) {
+ gtk_text_buffer_apply_tag_by_name(buffer, "yellow-bg", &match_start, &match_end);
+ offset = gtk_text_iter_get_offset(&match_end);
+ gtk_text_buffer_get_iter_at_offset(buffer, &find_start, offset);
+ cnt++;
+ }
+
+ if (!cnt) {
+ char status_msg[50] = {0};
+ sprintf(status_msg, "Word '%s' was not found", word);
+ gtk_statusbar_pop(GTK_STATUSBAR(statusbar), find_id);
+ gtk_statusbar_push(GTK_STATUSBAR(statusbar), find_id, (gchar *) status_msg);
+ }
+
+ gtk_text_buffer_get_start_iter(buffer, &find_start);
+ gtk_text_buffer_get_end_iter(buffer, &find_end);
+ if (gtk_text_iter_search_word(&find_start, word, GTK_TEXT_SEARCH_TEXT_ONLY|
+ GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start,
+ &match_end, NULL, SEARCH_FORWARD)) {
+ gtk_text_buffer_apply_tag_by_name(buffer, "green-bg", &match_start, &match_end);
+ current_highlighted_end = gtk_text_iter_get_offset(&match_end);
+ current_highlighted_start = gtk_text_iter_get_offset(&match_start);
+ gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(sentences_text), &match_start, 0.0, TRUE, 0.5, 0.5);
+ }
+}
+
+static void set_find_text(gchar *text)
+{
+ gtk_entry_set_text(GTK_ENTRY(find_entry), text);
+}
+
+static void clear_search_tags()
+{
+ GtkTextIter start, end;
+
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(sentences_text));
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ gtk_text_buffer_remove_tag_by_name(buffer, "yellow-bg", &start, &end);
+ gtk_text_buffer_remove_tag_by_name(buffer, "green-bg", &start, &end);
+}
+
+/* We won't need this abomination if GTK developers implement
+ * SEARCH_CASE_INSENSITIVE flag in GtkTextSearchFlags struct
+ * which is in their TODO list
+ */
+static gboolean gtk_text_iter_search_word(const GtkTextIter *iter, const gchar *str,
+ GtkTextSearchFlags flags, GtkTextIter *match_start,
+ GtkTextIter *match_end, const GtkTextIter *limit,
+ const int direction)
+{
+ GtkTextIter match_start_wcap, match_end_wcap;
+ gboolean result = FALSE;
+ int offset, offset_wcap;
+ gchar *str_wcap;
+
+ str_wcap = malloc((strlen(str)+1)*sizeof(gchar));
+ strcpy(str_wcap, str);
+ /* We've lowered only first letter, so there are only two cases*/
+ *str_wcap = toupper(*str_wcap);
+ if (direction == SEARCH_FORWARD) {
+ if (gtk_text_iter_forward_search(iter, str, flags, match_start, match_end, limit))
+ offset = gtk_text_iter_get_offset(match_start);
+ else
+ offset = -1;
+ if (gtk_text_iter_forward_search(iter, str_wcap, flags, &match_start_wcap, &match_end_wcap, limit))
+ offset_wcap = gtk_text_iter_get_offset(&match_start_wcap);
+ else
+ offset_wcap = -1;
+ if (((offset_wcap < offset)||(offset == -1))&&(offset_wcap != -1)) {
+ *match_start = match_start_wcap;
+ *match_end = match_end_wcap;
+ }
+ } else if (direction == SEARCH_BACKWARD) {
+ if (gtk_text_iter_backward_search(iter, str, flags, match_start, match_end, limit))
+ offset = gtk_text_iter_get_offset(match_start);
+ else
+ offset = -1;
+ if (gtk_text_iter_backward_search(iter, str_wcap, flags, &match_start_wcap, &match_end_wcap, limit))
+ offset_wcap = gtk_text_iter_get_offset(&match_start_wcap);
+ else
+ offset_wcap = -1;
+ if (offset < offset_wcap) {
+ *match_start = match_start_wcap;
+ *match_end = match_end_wcap;
+ }
+ }
+ free(str_wcap);
+ if ((offset_wcap != -1)||(offset != -1))
+ result = TRUE;
+ return result;
+}
+
+static void find_other(const gchar *word, const int direction)
+{
+ GtkTextIter find_start, find_end;
+ GtkTextIter match_start, match_end;
+
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(sentences_text));
+ gtk_text_buffer_get_start_iter(buffer, &find_start);
+ gtk_text_buffer_get_end_iter(buffer, &find_end);
+ gtk_text_buffer_remove_tag_by_name(buffer, "green-bg", &find_start, &find_end);
+ if (direction == SEARCH_FORWARD) {
+ gtk_text_buffer_get_iter_at_offset(buffer, &find_start, current_highlighted_end);
+ } else if (direction == SEARCH_BACKWARD) {
+ gtk_text_buffer_get_iter_at_offset(buffer, &find_start, current_highlighted_start);
+ }
+ if (gtk_text_iter_search_word(&find_start, word, GTK_TEXT_SEARCH_TEXT_ONLY|
+ GTK_TEXT_SEARCH_VISIBLE_ONLY, &match_start,
+ &match_end, NULL, direction)) {
+ gtk_text_buffer_apply_tag_by_name(buffer, "green-bg", &match_start, &match_end);
+ current_highlighted_start = gtk_text_iter_get_offset(&match_start);
+ current_highlighted_end = gtk_text_iter_get_offset(&match_end);
+ gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(sentences_text), &match_start, 0.0, TRUE, 0.5, 0.5);
+ } else {
+ if (direction == SEARCH_FORWARD) {
+ gtk_text_buffer_get_end_iter(buffer, &find_end);
+ current_highlighted_start = gtk_text_iter_get_offset(&find_end);
+ current_highlighted_end = gtk_text_iter_get_offset(&find_end);
+ } else if (direction == SEARCH_BACKWARD) {
+ gtk_text_buffer_get_start_iter(buffer, &find_start);
+ current_highlighted_start = gtk_text_iter_get_offset(&find_start);
+ current_highlighted_end = gtk_text_iter_get_offset(&find_start);
+ }
+ }
+}
+
diff --git a/src/mainwin.h b/src/mainwin.h
new file mode 100644
index 0000000..bdf2f2b
--- /dev/null
+++ b/src/mainwin.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MAINWIN_H
+#define MAINWIN_H
+
+#include <gtk/gtk.h>
+
+extern GtkWidget *main_window;
+
+void create_main_window();
+void add_sentence(char *);
+void clear_sentences();
+
+#endif /*MAINWIN_H*/
diff --git a/src/srt.c b/src/srt.c
new file mode 100644
index 0000000..523eb5a
--- /dev/null
+++ b/src/srt.c
@@ -0,0 +1,145 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "main.h"
+#include "srt.h"
+#include "engparser.h"
+
+static int get_srt_tag_length(char *);
+
+/*
+ * Reads text lines from *.srt file
+ * NOTE that "\r\n" and "\n" line ends are possible
+ */
+int process_srt(FILE *subtitle)
+{
+ char line[MAXLINE] = {0};
+ int lines;
+
+ while (!feof(subtitle)) {
+ for (lines = 0; lines < 2; lines++) {
+ fgets(line, MAXLINE, subtitle);
+ if (feof(subtitle)) return 0;
+ }
+ fgets(line, MAXLINE, subtitle);
+ process_srt_line(line);
+ fgets(line, MAXLINE, subtitle);
+ if (!((line[0] == '\n')||((line[0] == '\r')&&(line[1] == '\n')))) {
+ process_srt_line(line);
+ fgets(line, MAXLINE, subtitle);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Recieves: line from *.srt file with final '\n' or "\r\n"
+ */
+int process_srt_line(char *line)
+{
+ char phrase[MAXPHRASE] = {0};
+ int i;
+ int taglength;
+
+ for (i = 0; !((line[0] == '\n')||((line[0] == '\r')&&(line[1] == '\n'))); i++, line++) {
+ while (*line == '<') {
+ if (!(taglength = get_srt_tag_length(line)))
+ break;
+ line += taglength;
+ }
+ if ((line[0] == '\n')||((line[0] == '\r')&&(line[1] == '\n')))
+ break;
+ phrase[i] = *line;
+ }
+ phrase[i] = '\n';
+ switch (lang) {
+ case ENG: parseengphrase(phrase);
+ }
+ return 0;
+}
+
+/*
+ * It processes tags and calculate it's length. Possible tags are:
+ * <font color="#00FF00" size="6">The <font size="35">most</font> difficult tag</font>
+ * <b><i><u>Some of formatted text</u></i></b>
+ * It also misses tags with mistakes
+ */
+static int get_srt_tag_length(char *line)
+{
+ char c;
+ int taglength;
+
+ if (line[1] == '/') {
+ c = line[2];
+ switch (c) {
+ case 'b': case 'i': case 'u':
+ taglength = 4;
+ break;
+ case 'f':
+ taglength = 7;
+ break;
+ default:
+ taglength = 0;
+ break;
+ }
+ }
+ else {
+ c = line[1];
+ switch (c) {
+ case 'b': case 'i': case 'u':
+ taglength = 3;
+ break;
+ case 'f':
+ taglength = 5;
+ c = line[5];
+ while (c == ' ') {
+ taglength++;
+ c = line[taglength];
+ switch (c) {
+ case 'c':
+ taglength += 15;
+ break;
+ case 's':
+ taglength += 6;
+ while isdigit(line[taglength])
+ taglength++;
+ taglength++;
+ break;
+ case '>':
+ break;
+ default:
+ taglength = 0;
+ }
+ c = line[taglength];
+ }
+ if (c == '>')
+ taglength++;
+ else
+ taglength = 0;
+ break;
+ default:
+ taglength = 0;
+ break;
+ }
+ }
+ return taglength;
+}
+
diff --git a/src/srt.h b/src/srt.h
new file mode 100644
index 0000000..12e8d4e
--- /dev/null
+++ b/src/srt.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SRT_H
+#define SRT_H
+
+int process_srt(FILE *);
+int process_srt_line(char *);
+
+#endif /*SRT_H*/
diff --git a/src/word.c b/src/word.c
new file mode 100644
index 0000000..00fbf42
--- /dev/null
+++ b/src/word.c
@@ -0,0 +1,232 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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;
+}
+
diff --git a/src/word.h b/src/word.h
new file mode 100644
index 0000000..fd31cb9
--- /dev/null
+++ b/src/word.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of WordExtract.
+ *
+ * Copyright (C) 2009 Borisov Alexandr
+ *
+ * WordExtract 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.
+ *
+ * WordExtract 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 WordExtract. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WORD_H
+#define WORD_H
+
+/* reffering to the Wikipedia, words, in common
+ * language, aren't longer than 22 letters
+ */
+#define WORDLENGTH 25
+
+#include "main.h"
+
+struct words {
+ char *word;
+ struct words *lsibl;
+ struct words *rsibl;
+};
+typedef struct words Word;
+typedef struct {
+ unsigned int count;
+ char **by_az;
+} SortedWords;
+
+/*binary tree of words from parsed file*/
+extern Word *words;
+/*sorted array of words*/
+extern SortedWords user_words;
+
+Word *add_word(Word *, char *);
+void del_word(Word **, char *);
+unsigned int get_words_count(const Word *);
+void free_words(Word *);
+SortedWords get_sorted(Word *);
+void save_words(FILE *, SortedWords, SaveOpt);
+
+#endif /*WORD_H*/