diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 17 | ||||
-rw-r--r-- | src/Makefile.in | 434 | ||||
-rw-r--r-- | src/confwin.c | 368 | ||||
-rw-r--r-- | src/confwin.h | 25 | ||||
-rw-r--r-- | src/dict.c | 109 | ||||
-rw-r--r-- | src/dict.h | 36 | ||||
-rw-r--r-- | src/dictwin.c | 403 | ||||
-rw-r--r-- | src/dictwin.h | 25 | ||||
-rw-r--r-- | src/engparser.c | 118 | ||||
-rw-r--r-- | src/engparser.h | 53 | ||||
-rw-r--r-- | src/main.c | 182 | ||||
-rw-r--r-- | src/main.h | 52 | ||||
-rw-r--r-- | src/mainwin.c | 815 | ||||
-rw-r--r-- | src/mainwin.h | 31 | ||||
-rw-r--r-- | src/srt.c | 145 | ||||
-rw-r--r-- | src/srt.h | 26 | ||||
-rw-r--r-- | src/word.c | 232 | ||||
-rw-r--r-- | src/word.h | 53 |
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&"e.excl_w_starting + &"e.excl_w_middle&"e.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*/ |