[Pinfo-devel] r31 - in pinfo/branches/cxx: . macros src

Nathanael Nerode neroden-guest at costa.debian.org
Mon Aug 22 21:00:16 UTC 2005


Author: neroden-guest
Date: 2005-08-22 21:00:13 +0000 (Mon, 22 Aug 2005)
New Revision: 31

Added:
   pinfo/branches/cxx/src/colors.cxx
   pinfo/branches/cxx/src/datatypes.cxx
   pinfo/branches/cxx/src/filehandling_functions.cxx
   pinfo/branches/cxx/src/initializelinks.cxx
   pinfo/branches/cxx/src/keyboard.cxx
   pinfo/branches/cxx/src/mainfunction.cxx
   pinfo/branches/cxx/src/manual.cxx
   pinfo/branches/cxx/src/menu_and_note_utils.cxx
   pinfo/branches/cxx/src/parse_config.cxx
   pinfo/branches/cxx/src/pinfo.cxx
   pinfo/branches/cxx/src/printinfo.cxx
   pinfo/branches/cxx/src/readlinewrapper.cxx
   pinfo/branches/cxx/src/regexp_search.cxx
   pinfo/branches/cxx/src/sigblock.cxx
   pinfo/branches/cxx/src/signal_handler.cxx
   pinfo/branches/cxx/src/snprintf.cxx
   pinfo/branches/cxx/src/utils.cxx
   pinfo/branches/cxx/src/video.cxx
Removed:
   pinfo/branches/cxx/src/colors.c
   pinfo/branches/cxx/src/datatypes.c
   pinfo/branches/cxx/src/filehandling_functions.c
   pinfo/branches/cxx/src/initializelinks.c
   pinfo/branches/cxx/src/keyboard.c
   pinfo/branches/cxx/src/mainfunction.c
   pinfo/branches/cxx/src/manual.c
   pinfo/branches/cxx/src/menu_and_note_utils.c
   pinfo/branches/cxx/src/parse_config.c
   pinfo/branches/cxx/src/pinfo.c
   pinfo/branches/cxx/src/printinfo.c
   pinfo/branches/cxx/src/readlinewrapper.c
   pinfo/branches/cxx/src/regexp_search.c
   pinfo/branches/cxx/src/sigblock.c
   pinfo/branches/cxx/src/signal_handler.c
   pinfo/branches/cxx/src/snprintf.c
   pinfo/branches/cxx/src/utils.c
   pinfo/branches/cxx/src/video.c
Modified:
   pinfo/branches/cxx/INSTALL
   pinfo/branches/cxx/configure.ac
   pinfo/branches/cxx/macros/Makefile.in
   pinfo/branches/cxx/src/Makefile.am
   pinfo/branches/cxx/src/common_includes.h
   pinfo/branches/cxx/src/parse_config.h
   pinfo/branches/cxx/src/utils.h
Log:
Make stuff compile with C++.



Modified: pinfo/branches/cxx/INSTALL
===================================================================
--- pinfo/branches/cxx/INSTALL	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/INSTALL	2005-08-22 21:00:13 UTC (rev 31)
@@ -1,13 +1,16 @@
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
-Foundation, Inc.
+Installation Instructions
+*************************
 
-   This file is free documentation; the Free Software Foundation gives
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
 unlimited permission to copy, distribute and modify it.
 
 Basic Installation
 ==================
 
-   These are generic installation instructions.
+These are generic installation instructions.
 
    The `configure' shell script attempts to guess correct values for
 various system-dependent variables used during compilation.  It uses
@@ -67,9 +70,9 @@
 Compilers and Options
 =====================
 
-   Some systems require unusual options for compilation or linking that
-the `configure' script does not know about.  Run `./configure --help'
-for details on some of the pertinent environment variables.
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
 
    You can give `configure' initial values for configuration parameters
 by setting variables in the command line or in the environment.  Here
@@ -82,7 +85,7 @@
 Compiling For Multiple Architectures
 ====================================
 
-   You can compile the package for more than one kind of computer at the
+You can compile the package for more than one kind of computer at the
 same time, by placing the object files for each architecture in their
 own directory.  To do this, you must use a version of `make' that
 supports the `VPATH' variable, such as GNU `make'.  `cd' to the
@@ -99,19 +102,19 @@
 Installation Names
 ==================
 
-   By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc.  You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
 
    You can specify separate installation prefixes for
 architecture-specific files and architecture-independent files.  If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
 
    In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
+options like `--bindir=DIR' to specify different values for particular
 kinds of files.  Run `configure --help' for a list of the directories
 you can set and what kinds of files go in them.
 
@@ -122,7 +125,7 @@
 Optional Features
 =================
 
-   Some packages pay attention to `--enable-FEATURE' options to
+Some packages pay attention to `--enable-FEATURE' options to
 `configure', where FEATURE indicates an optional part of the package.
 They may also pay attention to `--with-PACKAGE' options, where PACKAGE
 is something like `gnu-as' or `x' (for the X Window System).  The
@@ -137,11 +140,11 @@
 Specifying the System Type
 ==========================
 
-   There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on.  Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
 `--build=TYPE' option.  TYPE can either be a short name for the system
 type, such as `sun4', or a canonical name which has the form:
 
@@ -156,7 +159,7 @@
 need to know the machine type.
 
    If you are _building_ compiler tools for cross-compiling, you should
-use the `--target=TYPE' option to select the type of system they will
+use the option `--target=TYPE' to select the type of system they will
 produce code for.
 
    If you want to _use_ a cross compiler, that generates code for a
@@ -167,9 +170,9 @@
 Sharing Defaults
 ================
 
-   If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
 `configure' looks for `PREFIX/share/config.site' if it exists, then
 `PREFIX/etc/config.site' if it exists.  Or, you can set the
 `CONFIG_SITE' environment variable to the location of the site script.
@@ -178,7 +181,7 @@
 Defining Variables
 ==================
 
-   Variables not defined in a site shell script can be set in the
+Variables not defined in a site shell script can be set in the
 environment passed to `configure'.  However, some packages may run
 configure again during the build, and the customized values of these
 variables may be lost.  In order to avoid this problem, you should set
@@ -186,14 +189,18 @@
 
      ./configure CC=/usr/local2/bin/gcc
 
-will cause the specified gcc to be used as the C compiler (unless it is
-overridden in the site shell script).
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).  Here is a another example:
 
+     /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
+configuration-related scripts to be executed by `/bin/bash'.
+
 `configure' Invocation
 ======================
 
-   `configure' recognizes the following options to control how it
-operates.
+`configure' recognizes the following options to control how it operates.
 
 `--help'
 `-h'

Modified: pinfo/branches/cxx/configure.ac
===================================================================
--- pinfo/branches/cxx/configure.ac	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/configure.ac	2005-08-22 21:00:13 UTC (rev 31)
@@ -3,6 +3,7 @@
 #*
 #*  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
 #*  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+#*  Copyright 2005  Nathanael Nerode <neroden at gcc.gnu.org>
 #*
 #*  This program is free software; you can redistribute it and/or modify
 #*  it under the terms of version 2 of the GNU General Public License as
@@ -34,8 +35,8 @@
 # put the config into config.h
 AC_CONFIG_HEADERS([config.h])
 
-# id main dir by src/pinfo.c file
-AC_CONFIG_SRCDIR([src/pinfo.c])
+# id main dir by src/pinfo.cxx file
+AC_CONFIG_SRCDIR([src/pinfo.cxx])
 # helper scripts are in tools/
 AC_CONFIG_AUX_DIR([tools])
 
@@ -58,6 +59,8 @@
 ####################################################
 # find C compiler
 AC_PROG_CC
+# find C++ compiler
+AC_PROG_CXX
 
 # set correct LIBS for (almost obsolete) INTERACTIVE UNIX
 AC_ISC_POSIX

Modified: pinfo/branches/cxx/macros/Makefile.in
===================================================================
--- pinfo/branches/cxx/macros/Makefile.in	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/macros/Makefile.in	2005-08-22 21:00:13 UTC (rev 31)
@@ -1,8 +1,8 @@
-# Makefile.in generated by automake 1.7.9 from Makefile.am.
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
 # @configure_input@
 
-# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-# Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  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.
@@ -13,7 +13,6 @@
 # PARTICULAR PURPOSE.
 
 @SET_MAKE@
-
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
 VPATH = @srcdir@
@@ -21,7 +20,6 @@
 pkglibdir = $(libdir)/@PACKAGE@
 pkgincludedir = $(includedir)/@PACKAGE@
 top_builddir = ..
-
 am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
 INSTALL = @INSTALL@
 install_sh_DATA = $(install_sh) -c -m 644
@@ -35,7 +33,44 @@
 NORMAL_UNINSTALL = :
 PRE_UNINSTALL = :
 POST_UNINSTALL = :
+build_triplet = @build@
 host_triplet = @host@
+subdir = macros
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/macros/aclocal-include.m4 \
+	$(top_srcdir)/macros/codeset.m4 $(top_srcdir)/macros/curses.m4 \
+	$(top_srcdir)/macros/gettext.m4 $(top_srcdir)/macros/glibc2.m4 \
+	$(top_srcdir)/macros/glibc21.m4 $(top_srcdir)/macros/iconv.m4 \
+	$(top_srcdir)/macros/intdiv0.m4 $(top_srcdir)/macros/intmax.m4 \
+	$(top_srcdir)/macros/inttypes-pri.m4 \
+	$(top_srcdir)/macros/inttypes.m4 \
+	$(top_srcdir)/macros/inttypes_h.m4 \
+	$(top_srcdir)/macros/lcmessage.m4 \
+	$(top_srcdir)/macros/lib-ld.m4 \
+	$(top_srcdir)/macros/lib-link.m4 \
+	$(top_srcdir)/macros/lib-prefix.m4 \
+	$(top_srcdir)/macros/longdouble.m4 \
+	$(top_srcdir)/macros/longlong.m4 $(top_srcdir)/macros/nls.m4 \
+	$(top_srcdir)/macros/po.m4 \
+	$(top_srcdir)/macros/printf-posix.m4 \
+	$(top_srcdir)/macros/progtest.m4 \
+	$(top_srcdir)/macros/readline.m4 \
+	$(top_srcdir)/macros/signed.m4 \
+	$(top_srcdir)/macros/size_max.m4 \
+	$(top_srcdir)/macros/stdint_h.m4 \
+	$(top_srcdir)/macros/uintmax_t.m4 \
+	$(top_srcdir)/macros/ulonglong.m4 \
+	$(top_srcdir)/macros/wchar_t.m4 $(top_srcdir)/macros/wint_t.m4 \
+	$(top_srcdir)/macros/xsize.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/tools/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 ACLOCAL = @ACLOCAL@
 ALLOCA = @ALLOCA@
 AMDEP_FALSE = @AMDEP_FALSE@
@@ -53,6 +88,10 @@
 CPPFLAGS = @CPPFLAGS@
 CURSES_INCLUDES = @CURSES_INCLUDES@
 CURSES_LIBS = @CURSES_LIBS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -125,13 +164,18 @@
 XGETTEXT = @XGETTEXT@
 ac_ct_AR = @ac_ct_AR@
 ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
 ac_ct_RANLIB = @ac_ct_RANLIB@
 ac_ct_STRIP = @ac_ct_STRIP@
 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
 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 = @build@
 build_alias = @build_alias@
@@ -152,6 +196,7 @@
 libexecdir = @libexecdir@
 localstatedir = @localstatedir@
 mandir = @mandir@
+mkdir_p = @mkdir_p@
 oldincludedir = @oldincludedir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
@@ -164,25 +209,41 @@
 	curses.m4			\
 	readline.m4
 
-
 EXTRA_DIST = $(MACROS) autogen.sh
 MAINTAINERCLEANFILES = macros.dep
-subdir = macros
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-mkinstalldirs = $(SHELL) $(top_srcdir)/tools/mkinstalldirs
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-DIST_SOURCES =
-DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
 all: all-am
 
 .SUFFIXES:
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am  $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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  macros/Makefile'; \
 	cd $(top_srcdir) && \
 	  $(AUTOMAKE) --gnu  macros/Makefile
-Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in  $(top_builddir)/config.status
-	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+.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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
@@ -198,11 +259,7 @@
 ctags: CTAGS
 CTAGS:
 
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 
-top_distdir = ..
-distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
-
 distdir: $(DISTFILES)
 	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
 	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
@@ -215,7 +272,7 @@
 	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
 	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
 	    dir="/$$dir"; \
-	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
 	  else \
 	    dir=''; \
 	  fi; \
@@ -233,7 +290,6 @@
 check-am: all-am
 check: check-am
 all-am: Makefile
-
 installdirs:
 install: install-am
 install-exec: install-exec-am
@@ -254,7 +310,7 @@
 clean-generic:
 
 distclean-generic:
-	-rm -f $(CONFIG_CLEAN_FILES)
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
 
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
@@ -272,6 +328,8 @@
 
 dvi-am:
 
+html: html-am
+
 info: info-am
 
 info-am:
@@ -306,10 +364,10 @@
 
 .PHONY: all all-am check check-am clean clean-generic clean-libtool \
 	distclean distclean-generic distclean-libtool distdir dvi \
-	dvi-am info info-am install install-am install-data \
-	install-data-am install-exec install-exec-am install-info \
-	install-info-am install-man install-strip installcheck \
-	installcheck-am installdirs maintainer-clean \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-exec install-exec-am \
+	install-info install-info-am install-man install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
 	maintainer-clean-generic mostlyclean mostlyclean-generic \
 	mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
 	uninstall-info-am

Modified: pinfo/branches/cxx/src/Makefile.am
===================================================================
--- pinfo/branches/cxx/src/Makefile.am	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/Makefile.am	2005-08-22 21:00:13 UTC (rev 31)
@@ -5,19 +5,19 @@
 bin_PROGRAMS = pinfo
 
 
-pinfo_COMMON_SRC = pinfo.c \
-		colors.c \
-		datatypes.c \
-		filehandling_functions.c \
-		keyboard.c \
-		mainfunction.c \
-		manual.c \
-		menu_and_note_utils.c \
-		parse_config.c \
-		regexp_search.c \
-		signal_handler.c \
-		utils.c \
-		video.c \
+pinfo_COMMON_SRC = pinfo.cxx \
+		colors.cxx \
+		datatypes.cxx \
+		filehandling_functions.cxx \
+		keyboard.cxx \
+		mainfunction.cxx \
+		manual.cxx \
+		menu_and_note_utils.cxx \
+		parse_config.cxx \
+		regexp_search.cxx \
+		signal_handler.cxx \
+		utils.cxx \
+		video.cxx \
 		colors.h \
 		common_includes.h \
 		datatypes.h \
@@ -31,16 +31,16 @@
 		signal_handler.h \
 		utils.h \
 		video.h \
-		initializelinks.c \
+		initializelinks.cxx \
 		initializelinks.h \
-		printinfo.c \
+		printinfo.cxx \
 		printinfo.h \
 		localestuff.h \
 		rcsid.h
 
-pinfo_READLINE = readlinewrapper.c readlinewrapper.h 
-pinfo_SNPRINTF = snprintf.c # snprintf.h
-pinfo_SIGBLOCK = sigblock.c sigblock.h
+pinfo_READLINE = readlinewrapper.cxx readlinewrapper.h 
+pinfo_SNPRINTF = snprintf.cxx # snprintf.h
+pinfo_SIGBLOCK = sigblock.cxx sigblock.h
 
 if HAS_READLINE
 pinfo_READLINE_OBJ = 

Deleted: pinfo/branches/cxx/src/colors.c

Copied: pinfo/branches/cxx/src/colors.cxx (from rev 30, pinfo/branches/cxx/src/colors.c)

Modified: pinfo/branches/cxx/src/common_includes.h
===================================================================
--- pinfo/branches/cxx/src/common_includes.h	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/common_includes.h	2005-08-22 21:00:13 UTC (rev 31)
@@ -39,6 +39,7 @@
 #include <sys/stat.h>
 #include <pwd.h>
 #include <grp.h>
+#include <ctype.h>
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"

Deleted: pinfo/branches/cxx/src/datatypes.c

Copied: pinfo/branches/cxx/src/datatypes.cxx (from rev 30, pinfo/branches/cxx/src/datatypes.c)
===================================================================
--- pinfo/branches/cxx/src/datatypes.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/datatypes.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,191 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+#include "common_includes.h"
+
+RCSID("$Id$")
+
+int verbose = 1;
+
+char *filenameprefix = 0;
+
+char *httpviewer = "lynx";
+char *ftpviewer = "lynx";
+char *maileditor = "mail";
+char *printutility = "lpr";
+char *manlinks = "1:8:2:3:4:5:6:7:9:n:l:p:o:3X11:3Xt:3X:3x";
+char *configuredinfopath = "/usr/share/info:/usr/local/share/info:/opt/info";
+char *ignoredmacros = 0;
+char *rcfile = NULL;
+
+char *tmpfilename1 = 0;
+char *tmpfilename2 = 0;
+
+SearchAgain searchagain;
+
+HyperObject *hyperobjects = 0;
+int hyperobjectcount = 0;
+
+Indirect *indirect = 0;
+TagTable *tag_table = 0;
+long FirstNodeOffset = 0;
+char FirstNodeName[256];
+int IndirectEntries = 0;
+int TagTableEntries = 0;
+int maxx, maxy;
+int CutManHeaders = 0;
+int CutEmptyManLines = 0;
+int ForceManualTagTable = 0;
+int LongManualLinks = 0;
+char *ManOptions = "";
+char *StderrRedirection = "2> /dev/null";
+int FilterB7 = 0;
+int ConfirmQuit = 0;
+int QuitConfirmDefault = 0;
+int ClearScreenAtExit = 0;
+int CallReadlineHistory = 1;
+
+InfoHistory infohistory;
+
+int npos = -1;
+int ncursor = -1;
+int nmenu = -1;
+int use_apropos = 0;
+int plain_apropos = 0;
+int use_manual = 0;
+int use_raw_filename = 0;
+int quote_ignored = 0;
+
+int winchanged = 0;
+
+void
+inithistory()
+{
+	infohistory.length = 0;
+	infohistory.node = 0;
+	infohistory.file = 0;
+	infohistory.pos = 0;
+	infohistory.cursor = 0;
+	infohistory.menu = 0;
+}
+
+/*
+ * Add history entry
+ */
+void
+addinfohistory(char *file, char *node, int cursor, int menu, int pos)
+{
+	if (!infohistory.length)
+	{
+		infohistory.length++;
+		infohistory.node = (char**)xmalloc(sizeof(char *) * 2);
+		infohistory.node[0] = 0;
+		infohistory.file = (char**)xmalloc(sizeof(char *) * 2);
+		infohistory.file[0] = 0;
+		infohistory.pos = (int*)xmalloc(sizeof(int) * 2);
+		infohistory.cursor = (int*)xmalloc(sizeof(int) * 2);
+		infohistory.menu = (int*)xmalloc(sizeof(int) * 2);
+	}
+	else
+	{
+		infohistory.length++;
+		infohistory.node = (char**)xrealloc(infohistory.node, sizeof(char *) *(infohistory.length + 1));
+		infohistory.file = (char**)xrealloc(infohistory.file, sizeof(char *) *(infohistory.length + 1));
+		infohistory.pos = (int*)xrealloc(infohistory.pos, sizeof(int) *(infohistory.length + 1));
+		infohistory.cursor = (int*)xrealloc(infohistory.cursor, sizeof(int) *(infohistory.length + 1));
+		infohistory.menu = (int*)xrealloc(infohistory.menu, sizeof(int) *(infohistory.length + 1));
+	}
+	infohistory.node[infohistory.length] = (char*)xmalloc(strlen(node) + 1);
+	strcpy(infohistory.node[infohistory.length], node);
+	infohistory.file[infohistory.length] = (char*)xmalloc(strlen(file) + 1);
+	strcpy(infohistory.file[infohistory.length], file);
+	infohistory.pos[infohistory.length] = pos;
+	infohistory.cursor[infohistory.length] = cursor;
+	infohistory.menu[infohistory.length] = menu;
+}
+
+/*
+ * Delete last history entry
+ */
+void
+dellastinfohistory()
+{
+	if (infohistory.length)
+	{
+		if (infohistory.node[infohistory.length])
+		{
+			xfree(infohistory.node[infohistory.length]);
+			infohistory.node[infohistory.length] = 0;
+		}
+		if (infohistory.file[infohistory.length])
+		{
+			xfree(infohistory.file[infohistory.length]);
+			infohistory.file[infohistory.length] = 0;
+		}
+		if (infohistory.length)
+			infohistory.length--;
+		if (infohistory.length)
+		{
+			infohistory.node = (char**)xrealloc(infohistory.node, sizeof(char *) *(infohistory.length + 1));
+			infohistory.file = (char**)xrealloc(infohistory.file, sizeof(char *) *(infohistory.length + 1));
+			infohistory.pos = (int*)xrealloc(infohistory.pos, sizeof(int) *(infohistory.length + 1));
+			infohistory.cursor = (int*)xrealloc(infohistory.cursor, sizeof(int) *(infohistory.length + 1));
+			infohistory.menu = (int*)xrealloc(infohistory.menu, sizeof(int) *(infohistory.length + 1));
+		}
+		else
+		{
+			if (infohistory.node)
+			{
+				xfree(infohistory.node);
+				infohistory.node = 0;
+			}
+			if (infohistory.file)
+			{
+				xfree(infohistory.file);
+				infohistory.file = 0;
+			}
+			if (infohistory.pos)
+			{
+				xfree(infohistory.pos);
+				infohistory.pos = 0;
+			}
+			if (infohistory.cursor)
+			{
+				xfree(infohistory.cursor);
+				infohistory.cursor = 0;
+			}
+			if (infohistory.menu)
+			{
+				xfree(infohistory.menu);
+				infohistory.menu = 0;
+			}
+		}
+	}
+}
+
+void
+clearfilenameprefix()
+{
+	if (filenameprefix)
+	{
+		xfree(filenameprefix);
+		filenameprefix = 0;
+	}
+}

Deleted: pinfo/branches/cxx/src/filehandling_functions.c

Copied: pinfo/branches/cxx/src/filehandling_functions.cxx (from rev 30, pinfo/branches/cxx/src/filehandling_functions.c)
===================================================================
--- pinfo/branches/cxx/src/filehandling_functions.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/filehandling_functions.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,1181 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *  Copyright 2005  Nathanael Nerode <neroden at gcc.gnu.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+
+#include "common_includes.h"
+
+RCSID("$Id$")
+
+typedef struct
+{
+	char *suffix;
+	char *command;
+}
+Suffixes;
+
+char * basename(char *filename);
+
+
+/******************************************************************************
+ * This piece of declarations says what to do with info files stored with      *
+ * different formats/compression methods, before putting them into a temporary *
+ * file. I.e. you don't do anything to plain `.info' suffix; for a `.info.gz'  *
+ * you dump the file through `gunzip -d -c', etc.                              *
+ ******************************************************************************/
+
+#define SuffixesNumber 4
+
+Suffixes suffixes[SuffixesNumber] =
+{
+	{"", 		"cat"},
+	{".gz",		"gzip -d -q -c"},
+	{".Z",		"gzip -d -q -c"},
+	{".bz2",	"bzip2 -d -c"}
+};
+
+/*****************************************************************************/
+
+char **infopaths = 0;
+int infopathcount = 0;
+
+int
+qsort_cmp(const void *base, const void *compared)
+{
+	char *cbase =((TagTable *) base)->nodename;
+	char *ccompared =((TagTable *) compared)->nodename;
+	return compare_tag_table_string(cbase, ccompared);
+}
+
+int
+matchfile(char **buf, char *name)
+{
+#define Buf	(*buf)
+	DIR *dir;
+	char *bname=basename(name);
+	struct dirent *dp;
+	int namelen = strlen(bname);
+	int matched = 0;
+	if (Buf[strlen(Buf)-1]!='/')
+		strcat(Buf,"/");
+	strncat(Buf,name,bname-name);
+	dir = opendir(Buf);	/* here we always have '/' at end */
+	if (dir == NULL)
+		return 1;
+	while ((dp = readdir(dir)) != NULL)
+	{
+		if (strncmp(dp->d_name, bname, namelen) == 0)
+		{
+			char *tmp = strdup(dp->d_name);
+			int dl;
+			strip_compression_suffix(tmp);
+			dl = strlen(tmp);
+			if ((!isdigit(tmp[dl - 1])) &&(!isalpha(tmp[namelen])))
+				/* if it's not eg. info-2.gz, but info.gz, the primary page
+				 * && it's not a different name(eg. gdbm instead gdb) */
+			{
+				if ((!matched) ||(strlen(tmp) < matched))
+				{
+					Buf[strlen(Buf) - matched - 1] = '\0';
+					strcat(Buf, "/");
+					strcat(Buf, tmp);
+					matched = strlen(tmp);
+				}
+			}
+		}
+	}
+	closedir(dir);
+	if (matched)
+		return 0;
+	return 1;
+#undef Buf
+}
+
+FILE *
+dirpage_lookup(char **type, char ***message, long *lines,
+		char *filename, char **first_node)
+{
+#define Type	(*type)
+#define Message	(*message)
+#define Lines	(*lines)
+	FILE *id = 0;
+	int filenamelen = strlen(filename);
+	int goodHit = 0, perfectHit = 0;
+	char name[256];
+	char file[256];
+	int i;
+	id = opendirfile(0);
+	if (!id)
+		return 0;
+	read_item(id, type, message, lines);
+	for (i = 1; i < Lines; i++)	/* initialize node-links for every line */
+	{
+		if ((Message[i][0] == '*') &&(Message[i][1] == ' ') &&(!perfectHit))
+		{
+			char *nameend = strchr(Message[i], ':');
+			if (nameend)
+			{
+				if (*(nameend + 1) != ':')	/* form: `* name:(file)node.' */
+				{
+					char *filestart = strchr(nameend, '(');
+					if (filestart)
+					{
+						char *fileend = strchr(filestart, ')');
+						if (fileend)
+						{
+							char *dot = strchr(fileend, '.');
+							if (dot)
+							{
+								if (strncmp(filename, Message[i] + 2, filenamelen) == 0)
+								{
+									char *tmp = name;
+									strncpy(file, filestart + 1, fileend - filestart - 1);
+									file[fileend - filestart - 1] = 0;
+									strncpy(name, fileend + 1, dot - fileend - 1);
+									name[dot - fileend - 1] = 0;
+									while (isspace(*tmp))
+										tmp++;
+									if (strlen(name))
+									{
+										*first_node = (char*)xmalloc(strlen(tmp) + 1);
+										strcpy((*first_node), tmp);
+									}
+									if (id)
+										fclose(id);	/* we don't need dirfile/badly matched infofile open anymore */
+									id = 0;
+									if (!strstr(file, ".info"))
+										strcat(file, ".info");
+									id = openinfo(file, 0);
+									goodHit = 1;
+									if ((nameend - Message[i]) - 2 == filenamelen)	/* the name matches perfectly to the query */
+										perfectHit = 1;	/* stop searching for another matches, and use this one */
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	if (!goodHit)
+	{
+		fclose(id);
+		id = 0;
+	}
+	return id;
+#undef Lines
+#undef Message
+#undef Type
+}
+
+void
+freeitem(char **type, char ***buf, long *lines)
+{
+#define Type	(*type)
+#define Buf		(*buf)
+#define Lines	(*lines)
+	long i;
+
+	if (Type != 0)
+	{
+		xfree(Type);
+		Type = 0;
+	}
+	if (Buf != 0)
+	{
+		for (i = 1; i <= Lines; i++)
+			if (Buf[i] != 0)
+			{
+				xfree(Buf[i]);
+				Buf[i] = 0;
+			}
+		xfree(Buf);
+		Buf = 0;
+	}
+#undef Type
+#undef Buf
+#undef Lines
+}
+
+void
+read_item(FILE * id, char **type, char ***buf, long *lines)
+{
+
+#define Type	(*type)
+#define Buf		(*buf)
+#define Lines	(*lines)
+
+	freeitem(type, buf, lines);	/* free previously allocated memory */
+
+	while (fgetc(id) != INFO_TAG);	/*
+									 * seek precisely on the INFO_TAG
+									 *(the seeknode function may be
+									 * imprecise in combination with
+									 * some weird tag_tables).
+									 */
+	while (fgetc(id) != '\n');	/* then skip the trailing `\n' */
+
+	Type = (char*)xmalloc(1024);	/* read the header line */
+	fgets(Type, 1024, id);
+	Type = (char*)xrealloc(Type, strlen(Type) + 1);
+	Lines = 0;			/* set number of lines to 0 */
+
+	Buf = (char**)xmalloc(sizeof(char **));	/* initial buffer allocation */
+	do
+	{
+		if (feof(id))		/* don't read after eof in info file */
+			break;
+		if (Lines)		/* make a reallocation for new input line */
+		{
+			Buf[Lines] = (char*)xrealloc(Buf[Lines], strlen(Buf[Lines]) + 1);
+		}
+		Lines++;			/* increase the read lines number */
+
+		Buf = (char**)xrealloc(Buf, sizeof(char **) *(Lines + 1));
+		Buf[Lines] = (char*)xmalloc(1024);
+		Buf[Lines][0] = 0;
+
+		if (fgets(Buf[Lines], 1024, id) == NULL)		/*
+														 * if the line was not found
+														 * in input file,
+														 * fill the allocated space
+														 * with empty line.
+														 */
+			strcpy(Buf[Lines], "\n");
+	}
+	while (Buf[Lines][0] != INFO_TAG);	/* repeat until new node mark is found */
+
+
+	if (Lines)			/* added for simplifing two-line ismenu and isnote functs */
+	{
+		strcpy(Buf[Lines], "\n");
+		Buf[Lines] = (char*)xrealloc(Buf[Lines], strlen(Buf[Lines]) + 1);
+	}
+
+	fseek(id, -2, SEEK_CUR);
+#undef Type
+#undef Buf
+#undef Lines
+
+}
+void
+load_indirect(char **message, long lines)
+{
+	long i;
+	char *wsk;
+	int cut = 0;			/* number of invalid entries */
+	indirect = (Indirect*)xmalloc((lines + 1) * sizeof(Indirect));
+	for (i = 1; i < lines; i++)
+	{
+		char *check;
+		wsk = message[i];
+		check = wsk + strlen(wsk);
+		while (*(++wsk) != ':')	/* check if this line keeps a real entry */
+		{
+			if (wsk == check)	/*
+								 * make sure wsk won't go out of range
+								 * in case the wsk would be corrupted.
+								 */
+				break;
+		}
+		if (*wsk)			/* if the entry holds some data... */
+		{
+			(*wsk) = 0;
+			strncpy(indirect[i - cut].filename, message[i], 200);
+			(*wsk) = ':';
+			indirect[i - cut].offset = atoi(wsk + 2);
+		}
+		else
+			cut++;			/* if the entry was invalid, make inirect count shorter */
+	}
+	IndirectEntries = lines - 1 - cut;
+}
+
+void
+load_tag_table(char **message, long lines)
+{
+	long i;
+	char *wsk, *wsk1;
+	int is_indirect = 0;
+	register unsigned int j;
+	register char *res;
+	int cut = 0;			/* holds the number of corrupt lines */
+
+	/*
+	 * if in the first line there is a(indirect) string, skip that line
+	 * by adding the value of is_indirect=1 to all message[line] references.
+	 */
+	if (strcasecmp("(Indirect)", message[1]) == 0)
+		is_indirect = 1;
+	tag_table = (TagTable*)xmalloc((lines + 1) * sizeof(TagTable));
+	for (i = 1; i < lines - is_indirect; i++)
+	{
+		char *check;
+		wsk = message[i + is_indirect];
+		check = wsk + strlen(wsk);
+		while (!isspace(*(++wsk)))
+		{
+			if (wsk >= check)
+			{
+				wsk--;
+				break;
+			}
+		}
+		wsk++;
+		wsk1 = wsk;
+		check = wsk1 + strlen(wsk1);
+		while (*(++wsk1) != INDIRECT_TAG)
+		{
+			if (wsk1 >= check)
+				break;
+		}
+		if (wsk1 < check)
+		{
+			(*wsk1) = 0;
+			/*
+			 * original: sprintf(tag_table[i-cut].nodename,"%s",wsk);
+			 * below is a faster version.
+			 */
+			res = (char*)memcpy(tag_table[i - cut].nodename, wsk, j =(size_t)(wsk1 - wsk));
+			(*(res += j + 1)) = 0;
+			(*wsk1) = INDIRECT_TAG;
+			wsk1++;
+			tag_table[i - cut].offset = atoi(wsk1);
+		}
+		else
+			cut++;			/* increment the number of corrupt entries */
+	}
+	TagTableEntries = lines - 1 - is_indirect - cut;
+
+	/* FIXME: info should ALWAYS start at the 'Top' node, not at the first
+	   mentioned node(vide ocaml.info) */
+
+	for (i = 1; i <= TagTableEntries; i++)
+	{
+		if (strcasecmp(tag_table[i].nodename, "Top") == 0)
+		{
+			FirstNodeOffset = tag_table[i].offset;
+			strcpy(FirstNodeName, tag_table[i].nodename);
+		}
+	}
+	qsort(&tag_table[1], TagTableEntries, sizeof(TagTable), qsort_cmp);
+}
+
+int
+seek_indirect(FILE * id)
+{
+	int finito = 0;
+	long seek_pos;
+	int input;
+	char *type = (char*)xmalloc(1024);
+	fseek(id, 0, SEEK_SET);
+	while (!finito)		/*
+						 * scan through the file, searching for "indirect:"
+						 * string in the type(header) line of node.
+						 */
+	{
+		while ((input = fgetc(id)) != INFO_TAG)
+			if (input == EOF)
+			{
+				if (type)
+				{
+					xfree(type);
+					type = 0;
+				}
+				return 0;
+			}
+		seek_pos = ftell(id) - 2;
+		fgetc(id);
+		fgets(type, 1024, id);
+		if (strncasecmp("Indirect:", type, strlen("Indirect:")) == 0)
+		{
+			finito = 1;
+		}
+	}
+	xfree(type);
+	type = 0;
+	if (!curses_open)
+		printf(_("Searching for indirect done\n"));
+	else
+	{
+		attrset(bottomline);
+		mvhline(maxy - 1, 0, ' ', maxx);
+		mvaddstr(maxy - 1, 0, _("Searching for indirect done"));
+		attrset(normal);
+	}
+	fseek(id, seek_pos, SEEK_SET);
+	return 1;
+}
+
+/*
+ * second arg for dumping out verbose debug info or not :)
+ */
+int
+seek_tag_table(FILE * id,int quiet)
+{
+	int finito = 0;
+	long seek_pos;
+	int input;
+	char *type = (char*)xmalloc(1024);
+	fseek(id, 0, SEEK_SET);
+	/*
+	 * Scan through the file, searching for a string
+	 * "Tag Table:" in the type(header) line of node.
+	 */
+	while (!finito)
+	{
+		while ((input = fgetc(id)) != INFO_TAG)
+		{
+			if (input == EOF)
+			{
+				if (!quiet)
+				{
+					if (!curses_open)
+						printf(_("Warning: could not find tag table\n"));
+					else
+					{
+						attrset(bottomline);
+						mvhline(maxy - 1, 0, ' ', maxx);
+						mvaddstr(maxy - 1, 0, _("Warning: could not find tag table"));
+						attrset(normal);
+					}
+				}
+				if (type)
+				{
+					xfree(type);
+					type = 0;
+				}
+				return 2;
+			}
+		}
+		seek_pos = ftell(id) - 2;
+		while (fgetc(id) != '\n')
+		{
+			if (feof(id))
+				break;
+		}
+		fgets(type, 1024, id);
+		if (strncasecmp("Tag Table:", type, strlen("Tag Table:")) == 0)
+		{
+			finito = 1;
+		}
+	}
+	xfree(type);
+	type = 0;
+	if (!curses_open)
+		printf(_("Searching for tag table done\n"));
+	else
+	{
+		attrset(bottomline);
+		mvhline(maxy - 1, 0, ' ', maxx);
+		mvaddstr(maxy - 1, 0, "Searching for tag table done");
+		attrset(normal);
+	}
+	fseek(id, seek_pos, SEEK_SET);
+	return 1;
+}
+
+inline void
+buildcommand(char *dest, char *command, char *filename, const char *tmpfilename)
+{
+	strcpy(dest, command);
+	strcat(dest, " ");
+	strcat(dest, filename);
+	strcat(dest, "> ");
+	strcat(dest, tmpfilename);
+}
+
+inline void
+builddircommand(char *dest, char *command, char *filename, const char *tmpfilename)
+{
+	strcpy(dest, command);
+	strcat(dest, " ");
+	strcat(dest, filename);
+	strcat(dest, ">> ");
+	strcat(dest, tmpfilename);
+}
+
+FILE *
+opendirfile(int number)
+{
+	FILE *id = NULL;
+	char buf[1024];		/* holds local copy of filename */
+	char *bufend;			/* points at the trailing 0 of initial name */
+	char command[1128];		/* holds command to evaluate for decompression of file */
+	int i, j;
+	char *tmpfilename;
+	int *fileendentries = (int*)xmalloc(infopathcount * sizeof(int));
+	int dir_found = 0;
+	int dircount = 0;
+	int lang_found;
+	struct stat status;
+
+	if (number == 0)		/* initialize tmp filename for file 1 */
+	{
+		if (tmpfilename1)
+		{
+			unlink(tmpfilename1);	/* erase old tmpfile */
+			free(tmpfilename1);
+		}
+		tmpfilename1 = tempnam("/tmp", NULL);
+		tmpfilename = tmpfilename1;	/* later we will refere only to tmp1 */
+	}
+	for (i = 0; i < infopathcount; i++)	/* go through all paths */
+	{
+		lang_found = 0;
+		strcpy(buf, infopaths[i]);	/* build a filename */
+		strcat(buf, "/");
+		if (getenv("LANG") != NULL)
+			strcat(buf, getenv("LANG"));
+		strcat(buf, "/dir");
+		/*
+		 * remember the bufend to make it
+		 * possible later to glue compression suffixes.
+		 */
+		bufend = buf;
+		bufend += strlen(buf);
+		for (j = 0; j < SuffixesNumber; j++)	/* go through all suffixes */
+		{
+			strcat(buf, suffixes[j].suffix);
+			if ((id = fopen(buf, "r")) != NULL)
+			{
+				fclose(id);
+				builddircommand(command, suffixes[j].command, buf, tmpfilename);
+				system(command);
+				lstat(tmpfilename, &status);
+				fileendentries[dircount] = status.st_size;
+				dircount++;
+				dir_found = 1;
+				lang_found = 1;
+			}
+			(*bufend) = 0;
+		}
+
+		/* same as above, but without $LANG support */
+		if (!lang_found)
+		{
+			strcpy(buf, infopaths[i]);	/* build a filename */
+			strcat(buf, "/");
+			strcat(buf, "dir");
+			/*
+			 * remember the bufend to make it possible later to glue
+			 * compression suffixes.
+			 */
+			bufend = buf;
+			bufend += strlen(buf);
+			for (j = 0; j < SuffixesNumber; j++)	/* go through all suffixes */
+			{
+				strcat(buf, suffixes[j].suffix);
+				if ((id = fopen(buf, "r")) != NULL)
+				{
+					fclose(id);
+					builddircommand(command, suffixes[j].command, buf, tmpfilename);
+					system(command);
+					lstat(tmpfilename, &status);
+					fileendentries[dircount] = status.st_size;
+					dircount++;
+					dir_found = 1;
+				}
+				(*bufend) = 0;
+			}
+		}
+	}
+	if (dir_found)
+		id = fopen(tmpfilename, "r");
+	/*
+	 * Filter the concatenated dir pages to exclude hidden parts of info
+	 * entries
+	 */
+	if (id)
+	{
+		char *tmp;
+		long filelen, i;
+		int aswitch = 0;
+		int firstswitch = 0;
+		dircount = 0;
+
+		fseek(id, 0, SEEK_END);
+		filelen = ftell(id);
+
+		tmp = (char*)xmalloc(filelen);
+		fseek(id, 0, SEEK_SET);
+		fread(tmp, 1, filelen, id);
+		fclose(id);
+		id = fopen(tmpfilename, "w");
+		for (i = 0; i < filelen; i++)
+		{
+			if (tmp[i] == INFO_TAG)
+			{
+				aswitch ^= 1;
+				if (!firstswitch)
+					fputc(tmp[i], id);
+				firstswitch = 1;
+			}
+			else if ((aswitch) ||(!firstswitch))
+				fputc(tmp[i], id);
+			if (i + 1 == fileendentries[dircount])
+			{
+				if (aswitch != 0)
+					aswitch = 0;
+				dircount++;	/* the last dircount should fit to the end of filelen */
+			}
+		}
+		fputc(INFO_TAG, id);
+		fputc('\n', id);
+		xfree(fileendentries);
+		fclose(id);
+		id = fopen(tmpfilename, "r");
+		xfree(tmp);
+
+		return id;
+	}
+	return NULL;
+}
+
+char *
+basename(char *filename)
+{
+	int len = strlen(filename);
+	char *a = filename + len;
+	while (a > filename)
+	{
+		a--;
+		if (*a == '/')
+			return a + 1;
+	}
+	return filename;		/* when it was a basename */
+}
+
+/*
+ * Note: openinfo is a function for reading info files, and putting
+ * uncompressed content into a temporary filename.  For a flexibility, there
+ * are two temporary files supported, i.e.  one for keeping opened info file,
+ * and second for i.e. regexp search across info nodes, which are in other
+ * info-subfiles.  The temporary file 1 is refrenced by number=0, and file 2 by
+ * number=1 Openinfo by default first tries the path stored in char
+ * *filenameprefix and then in the rest of userdefined paths.
+ */
+FILE *
+openinfo(char *filename, int number)
+{
+	FILE *id = NULL;
+	char *buf = (char*) xmalloc(1024);	/* holds local copy of filename */
+	char *bufend;			/* points at the trailing 0 of initial name */
+	char command[1128];		/* holds command to evaluate for decompression of file */
+	int i, j, twoloops;
+	char *tmpfilename;
+
+	if (strncmp(filename, "dir", 3) == 0)
+	{
+		xfree(buf);
+		return opendirfile(number);
+	}
+
+	if (number == 0)		/* initialize tmp filename for file 1 */
+	{
+		if (tmpfilename1)
+		{
+			unlink(tmpfilename1);	/* erase old tmpfile */
+			free(tmpfilename1);
+		}
+		tmpfilename1 = tempnam("/tmp", NULL);
+		tmpfilename = tmpfilename1;	/* later we will refere only to tmp1 */
+	}
+	else /* initialize tmp filename for file 2 */
+	{
+		if (tmpfilename2)
+		{
+			unlink(tmpfilename2);	/* erase old tmpfile */
+			free(tmpfilename2);
+		}
+		tmpfilename2 = tempnam("/tmp", NULL);
+		tmpfilename = tmpfilename2;	/* later we will refere only to tmp2 */
+	}
+
+	for (i = -1; i < infopathcount; i++)	/* go through all paths */
+	{
+		if (i == -1)
+		{
+			/*
+			 * no filenameprefix, we don't navigate around any specific
+			 * infopage set, so simply scan all directories for a hit
+			 */
+			if (!filenameprefix)
+				continue;
+			else
+			{
+				strcpy(buf, filenameprefix);	/* build a filename */
+				strcat(buf, "/");
+				strcat(buf, basename(filename));
+			}
+		}
+		else
+		{
+			strcpy(buf, infopaths[i]);	/* build a filename */
+			if (matchfile(&buf, filename) == 1)	/* no match found in this directory */
+				continue;
+		}
+		bufend = buf;
+		/*
+		 * remember the bufend to make it possible later to glue compression
+		 * suffixes.
+		 */
+		bufend += strlen(buf);
+		for (j = 0; j < SuffixesNumber; j++)	/* go through all suffixes */
+		{
+			strcat(buf, suffixes[j].suffix);
+			if ((id = fopen(buf, "r")) != NULL)
+			{
+				fclose(id);
+				clearfilenameprefix();
+				filenameprefix = strdup(buf);
+				{			/* small scope for removal of filename */
+					int prefixi, prefixlen = strlen(filenameprefix);
+					for (prefixi = prefixlen; prefixi--; prefixi > 0)
+						if (filenameprefix[prefixi] == '/')
+						{
+							filenameprefix[prefixi] = 0;
+							break;
+						}
+				}
+				buildcommand(command, suffixes[j].command, buf, tmpfilename);
+				system(command);
+				id = fopen(tmpfilename, "r");
+				if (id)
+				{
+					xfree(buf);
+					return id;
+				}
+			}
+			(*bufend) = 0;
+		}
+		if ((i == -1) &&(filenameprefix))	/* if we have a nonzero filename prefix,
+											   that is we view a set of infopages,
+											   we don't want to search for a page
+											   in all directories, but only in
+											   the prefix directory. Therefore
+											   break here. */
+			break;
+	}
+	xfree(buf);
+	return 0;
+}
+
+	void
+addrawpath(char *filename)
+{
+	int len = strlen(filename);
+	int i, pos;
+	char tmp;
+	for (i = len; i >= 0; i--)
+	{
+		if (filename[i] == '/')
+		{
+			tmp = filename[i+1];
+			filename[i+1] = 0;
+			pos = i+1;
+			break;
+		}
+	}
+	if (i < 0)
+		pos = -1;
+
+	infopaths = (char**)xrealloc(infopaths,(infopathcount + 3) *(sizeof(char *)));
+	for (i = infopathcount; i > 0; i--)	/* move entries to the right */
+		infopaths[i] = infopaths[i - 1];
+
+	if (pos > 0)
+		infopaths[0]=strdup(filename);	/* add new(raw) entry */
+	else
+		infopaths[0]=strdup("./");
+	infopathcount++;
+
+	if (pos > 0)			/* recreate original filename */
+		filename[pos] = tmp;
+}
+
+	int
+isininfopath(char *name)
+{
+	int i;
+	for (i = 0; i < infopathcount; i++)
+	{
+		if (strcmp(name, infopaths[i]) == 0)
+			return 1;		/* path already exists */
+	}
+	return 0;			/* path not found in previous links */
+}
+
+/* returns the number of chars ch in string str */
+unsigned int
+charcount(const char *str, const char ch)
+{
+	int num = 0;
+	const char *c;
+
+	c = str;
+	
+	while (*c != '\0')
+	{
+		if (*c++ == ch)
+			num++;
+	}
+	return num;
+}
+
+/* 
+ * find the paths where info files are to be found, 
+ * and put them in the global var infopaths[]
+ */
+void
+initpaths()
+{
+	char emptystr[1] = "";
+	char **paths = NULL;
+	char *infopath = NULL, *langpath = NULL;
+	char *c, *dir, *env;
+	char *rawlang = NULL, *lang = NULL, *langshort = NULL;
+	int ret;
+	unsigned int i, j, maxpaths, numpaths = 0, infolen, langlen;
+	size_t len;
+	struct stat sbuf;
+	ino_t *inodes;
+
+	/* first concat the paths */
+	env = getenv("INFOPATH");
+	if (env == NULL)
+	{
+		env = emptystr;
+	}
+	infolen = strlen(env) + strlen(configuredinfopath) + 2;
+	infopath = (char *) xmalloc( infolen );
+	strcat(infopath, env);
+	strcat(infopath, ":");
+	strcat(infopath, configuredinfopath);
+
+	/* alloc the paths[] array */
+	maxpaths = 3 * (charcount( infopath, ':' ) + 1); // *3 for $LANG
+	paths = (char **) xmalloc( maxpaths * sizeof(char *) );
+
+	/* split at ':' and put the path components into paths[] */
+	c = infopath;
+	while (dir = strsep(&c, ":"))
+	{
+		/* if this actually is a non-empty string, add it to paths[] */
+		if ( dir && strlen(dir)>0 ) 
+		{
+			paths[numpaths++] = dir;
+		}
+	}
+
+	/* get the current $LANG, if any (to use for localized info pages) */
+	rawlang = getenv("LANG");
+	if (rawlang) {
+		lang = strdup(rawlang);
+		/* fix the lang string */
+		for (i=0; lang[i]!='\0'; i++)
+		{
+			/* cut off the charset */
+			if (lang[i]=='.') 
+			{
+				lang[i]='\0';
+			}
+			/* if lang is sublocalized (nl_BE or so), also use short version */
+			if (lang[i]=='_' && langshort==NULL)
+			{
+				langshort = strdup(lang);
+				langshort[i] = '\0';
+			}
+		}
+	}
+	/* if we have a LANG defined, add paths with this lang to the paths[] */
+	if (lang && strlen(lang)>0 )
+	{
+		/* crude upper limit */
+		langlen = infolen + (strlen(lang)+2) * numpaths + 1;
+		if (langshort!=NULL) langlen *= 2;
+		langpath = (char *) xmalloc( langlen * sizeof(char) );
+
+		c = langpath; 
+		for (i=0; i<numpaths; i++)
+		{
+			/* TODO: check for negative return values of sprintf */
+			len = sprintf(c, "%s/%s", paths[i], lang);
+			/* add the lang specific dir at the beginning */
+			paths[numpaths+i] = paths[i];
+			paths[i] = c;
+
+			c += len+1;
+			
+			if (langshort) 
+			{
+				/* TODO: check for negative return values of sprintf */
+				len = sprintf(c, "%s/%s", paths[numpaths+i], langshort);
+				/* add the lang specific dir at the beginning */
+				paths[2*numpaths+i] = paths[numpaths+i];
+				paths[numpaths+i] = c;
+
+				c += len+1;
+			}
+
+		}
+		numpaths *= (langshort?3:2);
+	}
+
+#ifdef ___DEBUG___
+	/* for debugging */
+	for (i=0; i<numpaths; i++)
+		fprintf(stderr,"--> %s\n", paths[i]);
+#endif
+
+	/* ok, now we have all the (possibly) revelevant paths in paths[] */
+	/* now loop over them, see if they are valid and if they are duplicates*/
+	inodes = (ino_t *) xmalloc( maxpaths * sizeof(ino_t *) );
+	numpaths = 0;
+	len = 0;
+	for (i=0; i< maxpaths; i++)
+	{
+		/* stat() the dir */
+		ret = stat( paths[i], &sbuf);
+		/* and see if it could be opened */
+		if (ret < 0)
+		{
+#ifdef ___DEBUG___
+			fprintf(stderr, "error while opening `%s': %s\n", 
+					paths[i], strerror(errno) );
+#endif 
+			paths[i] = NULL;
+			inodes[i] = 0;
+		}
+		else
+		{
+			inodes[i] = sbuf.st_ino;
+		}
+
+		/* now check if this path is a duplicate */
+		for (j=0; j<i; j++)
+		{
+			if (inodes[j]==inodes[i]) paths[i] = NULL;
+		}
+
+		/* calculate the total number of vali paths and the size of teh strings */
+		if (paths[i]!=NULL) 
+		{
+			numpaths++;
+			len += strlen(paths[i]) + 1;
+		}
+	}
+
+
+	/* and alloc and copy to global var */
+	infopathcount = numpaths;
+	infopaths = (char **) xmalloc( numpaths * sizeof(char *) );
+	c = (char *) xmalloc( len * sizeof(char) );
+	j=0;
+	for (i=0; i<maxpaths; i++)
+	{
+		if (paths[i]!=NULL)
+		{
+			/* copy path to c buffer */
+			strcpy(c, paths[i]);	
+			infopaths[j++] = c;
+			c += strlen(paths[i]) + 1;
+		}
+	}
+	
+
+	xfree(infopath);
+	xfree(langpath);
+	xfree(paths);
+	xfree(lang);
+	xfree(langshort);
+	xfree(inodes);
+
+#ifdef ___DEBUG___
+	/* for debugging */
+	fprintf(stderr, "%i valid info paths found:\n", infopathcount);
+	for (i=0; i<infopathcount; i++)
+		if (infopaths[i]) fprintf(stderr,"--> %s\n", infopaths[i]);
+#endif
+
+
+}
+
+
+
+	void
+create_indirect_tag_table()
+{
+	FILE *id = 0;
+	int i, j, initial;
+	for (i = 1; i <= IndirectEntries; i++)
+	{
+		id = openinfo(indirect[i].filename, 1);
+		initial = TagTableEntries + 1;
+		if (id)
+		{
+			create_tag_table(id);
+			FirstNodeOffset = tag_table[1].offset;
+			strcpy(FirstNodeName, tag_table[1].nodename);
+		}
+		fclose(id);
+		for (j = initial; j <= TagTableEntries; j++)
+		{
+			tag_table[j].offset +=(indirect[i].offset - FirstNodeOffset);
+		}
+	}
+	FirstNodeOffset = tag_table[1].offset;
+	strcpy(FirstNodeName, tag_table[1].nodename);
+	qsort(&tag_table[1], TagTableEntries, sizeof(TagTable), qsort_cmp);
+}
+	void
+create_tag_table(FILE * id)
+{
+	char *buf = (char*)xmalloc(1024);
+	long oldpos;
+	fseek(id, 0, SEEK_SET);
+	if (!tag_table)
+		tag_table = (TagTable*)xmalloc((TagTableEntries + 2) * sizeof(TagTable));
+	else
+		tag_table = (TagTable*)xrealloc(tag_table,(TagTableEntries + 2) * sizeof(TagTable));
+	while (!feof(id))
+	{
+		if (fgetc(id) == INFO_TAG)	/* We've found a node entry! */
+		{
+			while (fgetc(id) != '\n');	/* skip '\n' */
+			TagTableEntries++;	/* increase the nuber of tag table entries */
+			oldpos = ftell(id);	/* remember this file position! */
+			/*
+			 * it is a an eof-fake-node (in some info files it happens, that
+			 * the eof'ish end of node is additionaly signalised by an INFO_TAG
+			 * We give to such node an unlike to meet nodename.
+			 */
+			if (fgets(buf, 1024, id) == NULL)
+			{
+				tag_table = (TagTable*)xrealloc(tag_table, sizeof(TagTable) *(TagTableEntries + 1));
+				strcpy(tag_table[TagTableEntries].nodename, "12#!@#4");
+				tag_table[TagTableEntries].offset = 0;
+			}
+			else
+			{
+				int colons = 0, i, j;
+				int buflen = strlen(buf);
+				for (i = 0; i < buflen; i++)
+				{
+					if (buf[i] == ':')
+						colons++;
+					if (colons == 2)	/*
+										 * the string after the second colon
+										 * holds the name of current node.
+										 * The name may then end with `.',
+										 * or with a newline, which is scanned
+										 * bellow.
+										 */
+					{
+						for (j = i + 2; j < buflen; j++)
+						{
+							if ((buf[j] == ',') ||(buf[j] == '\n'))
+							{
+								tag_table = (TagTable*)xrealloc(tag_table, sizeof(TagTable) *(TagTableEntries + 1));
+								buf[j] = 0;
+								buflen = j;
+								strcpy(tag_table[TagTableEntries].nodename, buf + i + 2);
+								tag_table[TagTableEntries].offset = oldpos - 2;
+								break;
+							}
+						}
+						break;
+					}
+				}		/* end: for loop, looking for second colon */
+			}			/* end: not a fake node */
+		}			/* end: we've found a node entry(INFO_TAG) */
+	}				/* end: global while loop, looping until eof */
+	xfree(buf);
+	buf = 0;
+	if (!indirect)
+	{
+		FirstNodeOffset = tag_table[1].offset;
+		strcpy(FirstNodeName, tag_table[1].nodename);
+		qsort(&tag_table[1], TagTableEntries, sizeof(TagTable), qsort_cmp);
+	}
+}
+
+	void
+seeknode(int tag_table_pos, FILE ** Id)
+{
+	int i;
+#define id	(*Id)
+	/*
+	 * Indirect nodes are seeked using a formula:
+	 * file-offset = tagtable_offset - indirect_offset +
+	 *             + tagtable[1]_offset
+	 */
+	if (indirect)	
+	{
+		for (i = IndirectEntries; i >= 1; i--)
+		{
+			if (indirect[i].offset <= tag_table[tag_table_pos].offset)
+			{
+				long off = tag_table[tag_table_pos].offset - indirect[i].offset + FirstNodeOffset - 4;
+				fclose(id);
+				id = openinfo(indirect[i].filename, 0);
+				if (id == NULL)
+				{
+					closeprogram();
+					printf(_("Error: could not open info file\n"));
+					exit(1);
+				}
+				if (off > 0)
+					fseek(id, off, SEEK_SET);
+				else
+					fseek(id, off, SEEK_SET);
+				break;
+			}
+		}
+	}
+	else
+	{
+		long off = tag_table[tag_table_pos].offset - 4;
+		if (off > 0)
+			fseek(id, off, SEEK_SET);
+		else
+			fseek(id, off, SEEK_SET);
+	}
+#undef id
+}
+
+	void
+strip_compression_suffix(char *file)	/* removes trailing .gz, .bz2, etc. */
+{
+	char *found = 0;
+	int j;
+	for (j = 0; j < SuffixesNumber; j++)
+	{
+		if (found = strstr(file, suffixes[j].suffix))
+		{
+			if (*(found + strlen(suffixes[j].suffix)) == 0)
+			{
+				*found = 0;
+				break;
+			}
+		}
+	}
+}
+

Deleted: pinfo/branches/cxx/src/initializelinks.c

Copied: pinfo/branches/cxx/src/initializelinks.cxx (from rev 30, pinfo/branches/cxx/src/initializelinks.c)
===================================================================
--- pinfo/branches/cxx/src/initializelinks.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/initializelinks.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,763 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+#include "common_includes.h"
+
+RCSID("$Id$")
+
+#define MENU_DOT 0
+#define NOTE_DOT 1
+
+int
+compare_hyperlink(const void *a, const void *b)
+{
+	return ((HyperObject *) a)->col -((HyperObject *) b)->col;
+}
+
+void
+sort_hyperlinks_from_current_line(long startlink, long endlink)
+{
+	qsort(hyperobjects + startlink, endlink - startlink, sizeof(HyperObject), compare_hyperlink);
+}
+
+/*
+ * Compares two strings, ignoring whitespaces(tabs, spaces)
+ */
+int
+compare_tag_table_string(char *base, char *compared)
+{
+	int i, j;
+
+	j = 0;
+
+	for (i = 0; base[i] != 0; i++)
+	{
+		if (base[i] != compared[j])
+		{
+			if ((isspace(compared[j])) &&(isspace(base[i])));	/* OK--two blanks */
+			else if (isspace(compared[j]))
+				i--;		/* index of `base' should be unchanged after for's i++ */
+			else if (isspace(base[i]))
+				j--;		/* index of `compared' stands in place
+							   and waits for base to skip blanks */
+			else
+				return (int) base[i] -(int) compared[j];
+		}
+		j++;
+	}
+	while (compared[j])		/* handle trailing whitespaces of variable `compared' */
+	{
+		if (!isspace(compared[j]))
+			return (int) base[i] -(int) compared[j];
+		j++;
+	}
+	return 0;
+}
+
+/*
+ * checks if an item belongs to tag table. returns 1 on success and 0 on
+ * failure.  It should be optimised...
+ */
+inline int
+exists_in_tag_table(char *item)
+{
+	if (gettagtablepos(item) != -1)
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * calculates the length of string between start and end, counting `\t' as
+ * filling up to 8 chars. (i.e. at line 22 tab will increment the counter by 2
+ * [8-(22-int(22/8)*8)] spaces)
+ */
+int
+calculate_len(char *start, char *end)
+{
+	int len = 0;
+	while (start < end)
+	{
+		len++;
+		if (*start == '\t')
+		{
+			len--;
+			len +=(8 -((len) -(((len) >> 3) << 3)));
+		}
+		start++;
+	}
+	return len;
+}
+
+void
+freelinks()			/* frees space allocated previously by node-links */
+{
+	int i;
+	if ((hyperobjects)&&(hyperobjectcount))
+		xfree(hyperobjects);
+	hyperobjects = 0;
+	hyperobjectcount = 0;
+}
+
+/*
+ * Finds url end.  It is recognized by an invalid character.
+ */
+char *
+findurlend(char *str)
+{
+	char *end;
+	char *allowedchars = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890-_/~.%=|:@­";
+	end = str;
+	while (strchr(allowedchars, *end) != NULL)
+		++end;
+	if (end > str)
+	{
+		if (*(end - 1) == '.')
+			end--;
+	}
+	return end;
+}
+
+/*
+ * Searchs for a note/menu delimiter.  it may be dot, comma, tab, or newline.
+ */
+char *
+finddot(char *str, int note)
+{
+	char *ptr = str;
+	char *end[4] =
+	{
+		0, 0, 0, 0
+	};
+	char *closest = 0;
+	int i;
+	while (isspace(*ptr))	/* if there are only spaces and newline... */
+	{
+		if (*ptr == '\n')		/* then it's a `Menu:   \n' entry--skip it */
+			return 0;
+		ptr++;
+	}
+	end[0] = strrchr(str, '.');	/* nodename entry may end with dot, comma */
+	end[1] = strrchr(str, ',');	/* tabulation, or newline */
+	if (!note)
+	{
+		end[2] = strchr(str, '\t');
+		end[3] = strchr(str, '\n');
+	}
+	else
+		note = 2;
+	if (end[0])
+		closest = end[0];
+	else if (end[1])
+		closest = end[1];
+	else if (end[2])
+		closest = end[2];
+	else if (end[3])
+		closest = end[3];
+	for (i = 1; i < note; i++)	/* find the delimiter, which was found most
+								   recently */
+	{
+		if ((end[i] < closest) &&(end[i]))
+			closest = end[i];
+	}
+	return closest;
+}
+
+/*
+ * Moves you to the beginning of username in email address.  If username has
+ * length=0, NULL is returned.
+ */
+char *
+findemailstart(char *str)
+{
+	char *allowedchars = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890-_/~.%=|:";
+	char *at = strchr(str, '@');
+	char *emailstart = 0;
+	if (at)
+	{
+		emailstart = str;
+		while (at > str)
+		{
+			at--;
+			if (strchr(allowedchars, *at) == NULL)
+			{
+				if (*(at + 1) != '@')
+					return at + 1;
+				else
+					return 0;
+			}
+		}
+		if (*at != '@')
+			return at;
+		else
+			return 0;
+	}
+	return 0;
+}
+
+	void
+initializelinks(char *line1, char *line2, int line)
+{
+	char *tmp;
+	char *notestart = 0, *urlstart = 0, *urlend = 0;
+	char *quotestart = 0, *quoteend = 0;
+	char *buf = (char*)xmalloc(strlen(line1) + strlen(line2) + 1);
+	/* required to sort properly the hyperlinks from current line only */
+	long initialhyperobjectcount = hyperobjectcount;
+	int changed;
+	int line1len = strlen(line1);
+
+	strcpy(buf, line1);		/* copy two lines into one */
+	if (strlen(line1))
+		buf[strlen(line1) - 1] = ' ';	/* replace trailing '\n' with ' ' */
+	strcat(buf, line2);
+	/******************************************************************************
+	 * First scan for some highlights ;) -- words enclosed with quotes             *
+	 ******************************************************************************/
+	quoteend = buf;
+	do
+	{
+		changed = 0;
+		if ((quotestart = strchr(quoteend, '`')) != NULL)	/* find start of quoted text */
+		{
+			if (quotestart < buf + line1len)	/* if it's in the first line of the two glued together */
+				if ((quoteend = strchr(quotestart, '\'')) != NULL)		/* find the end of quoted text */
+				{
+					if (quoteend - quotestart > 1)
+					{
+						while (!strncmp(quoteend - 1, "n't", 3))	/* if this apostrophe is not a part of "haven't", "wouldn't", etc. */
+						{
+							quoteend = strchr(quoteend + 1, '\'');
+							if (!quoteend)
+								break;
+						}
+						if (quoteend)
+						{
+							changed = 1;
+							if (!hyperobjectcount)
+								hyperobjects = (HyperObject*)xmalloc(sizeof(HyperObject));
+							else
+								hyperobjects = (HyperObject*)xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
+							hyperobjects[hyperobjectcount].line = line;
+							hyperobjects[hyperobjectcount].col = calculate_len(buf, quotestart + 1);
+							hyperobjects[hyperobjectcount].breakpos = -1;	/* default */
+							if (quoteend > buf + line1len)
+							{
+								hyperobjects[hyperobjectcount].breakpos = buf + line1len - quotestart - 1;
+							}
+							hyperobjects[hyperobjectcount].type = HIGHLIGHT;
+							strncpy(hyperobjects[hyperobjectcount].node, quotestart + 1, quoteend - quotestart - 1);
+							hyperobjects[hyperobjectcount].node[quoteend - quotestart - 1] = 0;
+							strcpy(hyperobjects[hyperobjectcount].file, "");
+							hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+							hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+							hyperobjects[hyperobjectcount].tagtableoffset = -1;
+							hyperobjectcount++;
+						}
+					}
+				}
+		}
+	}
+	while (changed);
+	/******************************************************************************
+	 * Look for e-mail url's                                                       *
+	 ******************************************************************************/
+	urlend = line1;
+	do
+	{
+		changed = 0;
+		if ((urlstart = findemailstart(urlend)) != NULL)
+		{
+			urlend = findurlend(urlstart);	/* always successful */
+			if (!hyperobjectcount)
+				hyperobjects = (HyperObject*)xmalloc(sizeof(HyperObject));
+			else
+				hyperobjects = (HyperObject*)xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
+			hyperobjects[hyperobjectcount].line = line;
+			hyperobjects[hyperobjectcount].col = calculate_len(line1, urlstart);
+			hyperobjects[hyperobjectcount].breakpos = -1;
+			hyperobjects[hyperobjectcount].type = 6;
+			strncpy(hyperobjects[hyperobjectcount].node, urlstart, urlend - urlstart);
+			hyperobjects[hyperobjectcount].node[urlend - urlstart] = 0;
+			strcpy(hyperobjects[hyperobjectcount].file, "");
+			hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+			hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+			hyperobjects[hyperobjectcount].tagtableoffset = -1;
+			if (strchr(hyperobjects[hyperobjectcount].node, '.') == NULL)
+			{
+				if (!hyperobjectcount)
+					xfree(hyperobjects);
+			}
+			else
+				hyperobjectcount++;
+			changed = 1;
+		}
+
+	}
+	while (changed);
+	/******************************************************************************
+	 * First try to scan for menu. Use as many security mechanisms, as possible    *
+	 ******************************************************************************/
+
+	if ((line1[0] == '*') &&(line1[1] == ' '))	/* menu */
+	{
+		/******************************************************************************
+		 * Scan for normal menu of kind "*(infofile)reference:: comment",  where      *
+		 * the infofile parameter is optional, and indicates, that a reference         *
+		 * matches different info file.                                                *
+		 ******************************************************************************/
+		tmp = strstr(line1, "::");	/* "* menulink:: comment" */
+		if (tmp != NULL)
+		{
+			if (!hyperobjectcount)
+				hyperobjects = (HyperObject*)xmalloc(sizeof(HyperObject));
+			else
+				hyperobjects = (HyperObject*)xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
+			if (line1[2] == '(')	/* if cross-info link */
+			{
+				char *end = strchr(line1, ')');
+				if ((end != NULL) &&(end < tmp))		/* if the ')' char was found, and was before '::' */
+				{
+					long FilenameLen =(long)(end - line1 - 3);
+					long NodenameLen =(long)(tmp - end - 1);
+					strncpy(hyperobjects[hyperobjectcount].file,
+							line1 + 3, FilenameLen);
+					hyperobjects[hyperobjectcount].file[FilenameLen] = 0;
+					strncpy(hyperobjects[hyperobjectcount].node,
+							end + 1, NodenameLen);
+					hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
+					hyperobjects[hyperobjectcount].type = 0;
+					hyperobjects[hyperobjectcount].line = line;
+					hyperobjects[hyperobjectcount].col = 2;
+					hyperobjects[hyperobjectcount].breakpos = -1;
+					hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+					hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+					hyperobjectcount++;
+				}
+			}
+			else
+				/* if not cross-info link */
+			{
+				long NodenameLen =(long)(tmp - line1 - 2);
+				int goodHit = 0;
+				strcpy(hyperobjects[hyperobjectcount].file, "");
+				strncpy(hyperobjects[hyperobjectcount].node,
+						line1 + 2, NodenameLen);
+				hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
+				hyperobjects[hyperobjectcount].type = 0;
+				hyperobjects[hyperobjectcount].line = line;
+				hyperobjects[hyperobjectcount].col = 2;
+				hyperobjects[hyperobjectcount].breakpos = -1;
+				hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+				hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+				if (exists_in_tag_table(hyperobjects[hyperobjectcount].node))
+				{
+					hyperobjectcount++;	/* yep, this was a good hit */
+					goodHit = 1;
+				}
+				if (!goodHit)
+				{
+					if (!hyperobjectcount)
+					{
+						xfree(hyperobjects);
+						hyperobjects = 0;
+					}
+				}
+			}
+		}
+		/******************************************************************************
+		 * Scan for menu references of form                                            *
+		 * "* Comment:[spaces](infofile)reference."                                    *
+		 ******************************************************************************/
+		else if ((tmp = strrchr(line1, ':')) != NULL)
+		{
+			char *start = 0, *end = 0, *dot = 0;
+			dot = finddot(tmp + 1, MENU_DOT);	/* find the trailing dot */
+			if (dot != NULL)
+				if (dot + 7 < dot + strlen(dot))
+				{
+					/* skip possible '.info' filename suffix when searching for ending dot */
+					if (strncmp(dot, ".info)", 6) == 0)
+						dot = finddot(dot + 1, MENU_DOT);
+				}
+			/* we make use of sequential AND evaluation: start must not be NULL! */
+			if (((start = strchr(tmp, '(')) != NULL) &&(dot != NULL) &&
+					((end = strchr(start, ')')) != NULL))
+			{
+				if (start < dot)	/* security mechanism ;) */
+				{
+					if (end < dot)	/* security mechanism ;)) */
+					{
+						long FilenameLen =(long)(end - start - 1);
+						long NodenameLen =(long)(dot - end - 1);
+						if (!hyperobjectcount)
+							hyperobjects = (HyperObject*)xmalloc(sizeof(HyperObject));
+						else
+							hyperobjects = (HyperObject*)xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
+						strncpy(hyperobjects[hyperobjectcount].file,
+								start + 1, FilenameLen);
+						hyperobjects[hyperobjectcount].file[FilenameLen] = 0;
+						strncpy(hyperobjects[hyperobjectcount].node,
+								end + 1, NodenameLen);
+						hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
+						hyperobjects[hyperobjectcount].type = 1;
+						hyperobjects[hyperobjectcount].line = line;
+						hyperobjects[hyperobjectcount].col = calculate_len(line1, start);
+						hyperobjects[hyperobjectcount].breakpos = -1;
+						hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+						hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+						hyperobjectcount++;
+					}
+				}
+				else
+				{
+					goto handle_no_file_menu_label;
+				}
+			}
+			else if (dot != NULL)	/* if not cross-info reference */
+			{
+handle_no_file_menu_label:
+				{
+					long NodenameLen;
+					int goodHit = 0;	/* has val of 1, if it's a good hit */
+					if (!hyperobjectcount)
+						hyperobjects = (HyperObject*)xmalloc(sizeof(HyperObject));
+					else
+						hyperobjects = (HyperObject*)xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
+
+					start = tmp + 1;	/* move after the padding spaces */
+					while (isspace(*start))
+						start++;
+					NodenameLen =(long)(dot - start);
+					strcpy(hyperobjects[hyperobjectcount].file, "");
+					strncpy(hyperobjects[hyperobjectcount].node,
+							start, NodenameLen);
+					hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
+					hyperobjects[hyperobjectcount].type = 1;
+					hyperobjects[hyperobjectcount].line = line;
+					hyperobjects[hyperobjectcount].col = calculate_len(line1, start);
+					hyperobjects[hyperobjectcount].breakpos = -1;
+					hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+					hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+					if (exists_in_tag_table(hyperobjects[hyperobjectcount].node))
+					{
+						hyperobjectcount++;		/* yep, this was a good hit */
+						goodHit = 1;
+					}
+					if (!goodHit)
+					{
+						if (!hyperobjectcount)
+						{
+							xfree(hyperobjects);
+							hyperobjects = 0;
+						}
+					}
+				}
+			}
+		}
+	}
+	/******************************************************************************
+	 * Handle notes. In similar way as above.                                      *
+	 ******************************************************************************/
+	else if ((notestart = strstr(buf, "*note")) != NULL)
+		goto handlenote;
+	else if ((notestart = strstr(buf, "*Note")) != NULL)
+	{
+handlenote:
+		/******************************************************************************
+		 * Scan for normal note of kind "*(infofile)reference:: comment", where       *
+		 * the infofile parameter is optional, and indicates, that a reference         *
+		 * matches different info file.                                                *
+		 ******************************************************************************/
+		/* make sure that we don't handle notes, which fit in the second line */
+		if ((long)(notestart - buf) < strlen(line1))
+		{
+			/* we can handle only those, who are in the first line, or who are split up into two lines */
+			tmp = strstr(notestart, "::");	/* "*note notelink:: comment" */
+			if (tmp != NULL)
+			{
+				if (!hyperobjectcount)
+					hyperobjects = (HyperObject*)xmalloc(sizeof(HyperObject));
+				else
+					hyperobjects = (HyperObject*)xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
+				if (notestart[6] == '(')	/* if cross-info link */
+				{
+					char *end = strchr(notestart, ')');
+					if ((end != NULL) &&(end < tmp))	/* if the ')' char was found, and was before '::' */
+					{
+						long FilenameLen =(long)(end - notestart - 7);
+						long NodenameLen =(long)(tmp - end - 1);
+						strncpy(hyperobjects[hyperobjectcount].file,
+								notestart + 7, FilenameLen);
+						hyperobjects[hyperobjectcount].file[FilenameLen] = 0;
+						strncpy(hyperobjects[hyperobjectcount].node,
+								end + 1, NodenameLen);
+						hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
+						hyperobjects[hyperobjectcount].type = 2;
+						if (notestart + 7 - buf < strlen(line1))
+						{
+							hyperobjects[hyperobjectcount].line = line;
+							hyperobjects[hyperobjectcount].col = calculate_len(buf, notestart + 7);
+							/* if the note highlight fits int first line */
+							if (tmp - buf < strlen(line1))
+								hyperobjects[hyperobjectcount].breakpos = -1;
+								/* we don't need to break highlighting int several lines */
+							else
+								hyperobjects[hyperobjectcount].breakpos = strlen(line1) -(long)(notestart + 7 - buf) + 1;	/* otherwise we need it */
+						}
+						else
+						{
+							hyperobjects[hyperobjectcount].line = line + 1;
+							hyperobjects[hyperobjectcount].col = calculate_len(buf + strlen(line1), notestart + 7);
+							if (tmp - buf < strlen(line1))	/* as above */
+								hyperobjects[hyperobjectcount].breakpos = -1;
+							else if ((hyperobjects[hyperobjectcount].breakpos = strlen(line1) -(long)(notestart + 7 - buf) + 1) == 0)
+								hyperobjects[hyperobjectcount].line--;
+						}
+						hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+						hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+						hyperobjectcount++;
+					}
+				}
+				else /* if not cross-info link */
+				{
+					long NodenameLen =(long)(tmp - notestart - 6);
+					int goodHit = 0;
+					strcpy(hyperobjects[hyperobjectcount].file, "");
+					strncpy(hyperobjects[hyperobjectcount].node,
+							notestart + 6, NodenameLen);
+					hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
+					hyperobjects[hyperobjectcount].type = 2;
+					hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+					hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+					if (notestart + 7 - buf < strlen(line1))
+					{
+						hyperobjects[hyperobjectcount].line = line;
+						hyperobjects[hyperobjectcount].col = calculate_len(buf, notestart + 7) - 1;
+						/* if the note highlight fits int first line */
+						if (tmp - buf < strlen(line1))
+							hyperobjects[hyperobjectcount].breakpos = -1;	/* we don't need to break highlighting int several lines */
+						else
+							hyperobjects[hyperobjectcount].breakpos = strlen(line1) -(long)(notestart + 7 - buf) + 1;	/* otherwise we need it */
+					}
+					else
+					{
+						hyperobjects[hyperobjectcount].line = line + 1;
+						hyperobjects[hyperobjectcount].col = calculate_len(buf + strlen(line1), notestart + 7) - 1;
+						if (tmp - buf < strlen(line1))	/* as above */
+							hyperobjects[hyperobjectcount].breakpos = -1;
+						else if ((hyperobjects[hyperobjectcount].breakpos = strlen(line1) -(long)(notestart + 7 - buf) + 1) == 0)
+							hyperobjects[hyperobjectcount].line--;
+					}
+					if (exists_in_tag_table(hyperobjects[hyperobjectcount].node))
+					{
+						hyperobjectcount++;	/* yep, this was a good hit */
+						goodHit = 1;
+					}
+					if (!goodHit)
+					{
+						if (!hyperobjectcount)
+						{
+							xfree(hyperobjects);
+							hyperobjects = 0;
+						}
+					}
+				}
+			}
+			/******************************************************************************
+			 * Scan for note references of form                                            *
+			 * "* Comment:[spaces](infofile)reference."                                    *
+			 ******************************************************************************/
+			else if ((tmp = strstr(notestart, ":")) != NULL)
+			{
+				char *start = 0, *end = 0, *dot = 0;
+				dot = finddot(tmp + 1, NOTE_DOT);	/* find the trailing dot */
+				if (dot != NULL)
+					if (dot + 7 < dot + strlen(dot))
+					{
+						if (strncmp(dot, ".info)", 6) == 0)
+							dot = finddot(dot + 1, NOTE_DOT);
+					}
+				if (((start = strchr(tmp, '(')) != NULL) &&(dot != NULL) &&
+						((end = strchr(start, ')')) != NULL))	/* end may be found only if start is nonNULL!!! */
+				{
+					if (start < dot)	/* security mechanism ;) */
+					{
+						if (end < dot)	/* security mechanism ;)) */
+						{
+							long FilenameLen =(long)(end - start - 1);
+							long NodenameLen =(long)(dot - end - 1);
+							if (!hyperobjectcount)
+								hyperobjects = (HyperObject*)xmalloc(sizeof(HyperObject));
+							else
+								hyperobjects = (HyperObject*)xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
+							strncpy(hyperobjects[hyperobjectcount].file,
+									start + 1, FilenameLen);
+							hyperobjects[hyperobjectcount].file[FilenameLen] = 0;
+							strncpy(hyperobjects[hyperobjectcount].node,
+									end + 1, NodenameLen);
+							hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
+							hyperobjects[hyperobjectcount].type = 3;
+							if (start - buf < strlen(line1))
+							{
+								hyperobjects[hyperobjectcount].line = line;
+								hyperobjects[hyperobjectcount].col = calculate_len(buf, start);
+								if (dot - buf < strlen(line1))	/* if the note highlight fits in first line */
+									hyperobjects[hyperobjectcount].breakpos = -1;	/* we don't need to break highlighting int several lines */
+								else
+									hyperobjects[hyperobjectcount].breakpos = strlen(line1) -(long)(start - buf);	/* otherwise we need it */
+							}
+							else
+							{
+								hyperobjects[hyperobjectcount].line = line + 1;
+								hyperobjects[hyperobjectcount].col = calculate_len(buf + strlen(line1), start);
+								hyperobjects[hyperobjectcount].breakpos = -1;
+							}
+							hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+							hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+							hyperobjectcount++;
+						}
+					}
+					else
+					{
+						goto handle_no_file_note_label;
+					}
+				}
+				else if (dot != NULL)	/* if not cross-info reference */
+				{
+handle_no_file_note_label:
+					{
+						long NodenameLen;
+						int goodHit = 0;
+						if (!hyperobjectcount)
+							hyperobjects = (HyperObject*)xmalloc(sizeof(HyperObject));
+						else
+							hyperobjects = (HyperObject*)xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
+
+						start = tmp + 1;	/* move after the padding spaces */
+						while (isspace(*start))
+							start++;
+						NodenameLen =(long)(dot - start);
+						strcpy(hyperobjects[hyperobjectcount].file, "");
+						strncpy(hyperobjects[hyperobjectcount].node,
+								start, NodenameLen);
+						hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
+						hyperobjects[hyperobjectcount].type = 3;
+						hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+						hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+						if (start - buf < strlen(line1))
+						{
+							hyperobjects[hyperobjectcount].line = line;
+							hyperobjects[hyperobjectcount].col = calculate_len(buf, start);
+							if (dot - buf < strlen(line1))		/* if the note highlight fits in first line */
+								hyperobjects[hyperobjectcount].breakpos = -1;		/* we don't need to break highlighting int several lines */
+							else
+								hyperobjects[hyperobjectcount].breakpos = strlen(line1) -(long)(start - buf);	/* otherwise we need it */
+						}
+						else
+						{
+							hyperobjects[hyperobjectcount].line = line + 1;
+							hyperobjects[hyperobjectcount].col = calculate_len(strlen(line1) + buf, start);
+							hyperobjects[hyperobjectcount].breakpos = -1;
+						}
+						if (exists_in_tag_table(hyperobjects[hyperobjectcount].node))
+						{
+							hyperobjectcount++;	/* yep, this was a good hit */
+							goodHit = 1;
+						}
+						if (!goodHit)
+						{
+							if (!hyperobjectcount)
+							{
+								xfree(hyperobjects);
+								hyperobjects = 0;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	if (notestart)
+		if (notestart + 6 < buf + strlen(buf) + 1)
+		{
+			tmp = notestart;
+			if ((notestart = strstr(notestart + 6, "*Note")) != NULL)
+				goto handlenote;
+			notestart = tmp;
+			if ((notestart = strstr(notestart + 6, "*note")) != NULL)
+				goto handlenote;
+		}
+	/******************************************************************************
+	 * Try to scan for some url-like objects in single line; mainly               *
+	 * http://[address][space|\n|\t]                                              *
+	 * ftp://[address][space|\n|\t]                                               *
+	 * username at something.else[space|\n|\t]                                       *
+	 *****************************************************************************/
+	/* http:// */
+	urlend = line1;
+	while ((urlstart = strstr(urlend, "http://")) != NULL)
+	{
+		urlend = findurlend(urlstart);	/* always successful */
+		if (!hyperobjectcount)
+			hyperobjects = (HyperObject*)xmalloc(sizeof(HyperObject));
+		else
+			hyperobjects = (HyperObject*)xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
+		hyperobjects[hyperobjectcount].line = line;
+		hyperobjects[hyperobjectcount].col = calculate_len(line1, urlstart);
+		hyperobjects[hyperobjectcount].breakpos = -1;
+		hyperobjects[hyperobjectcount].type = 4;
+		strncpy(hyperobjects[hyperobjectcount].node, urlstart, urlend - urlstart);
+		hyperobjects[hyperobjectcount].node[urlend - urlstart] = 0;
+		strcpy(hyperobjects[hyperobjectcount].file, "");
+		hyperobjects[hyperobjectcount].tagtableoffset = -1;
+		hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+		hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+		hyperobjectcount++;
+	}
+	/* ftp:// */
+	urlend = line1;
+	while ((urlstart = strstr(urlend, "ftp://")) != NULL)
+	{
+		urlend = findurlend(urlstart);	/* always successful */
+		if (!hyperobjectcount)
+			hyperobjects = (HyperObject*)xmalloc(sizeof(HyperObject));
+		else
+			hyperobjects = (HyperObject*)xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
+		hyperobjects[hyperobjectcount].line = line;
+		hyperobjects[hyperobjectcount].col = calculate_len(line1, urlstart);
+		hyperobjects[hyperobjectcount].breakpos = -1;
+		hyperobjects[hyperobjectcount].type = 5;
+		strncpy(hyperobjects[hyperobjectcount].node, urlstart, urlend - urlstart);
+		hyperobjects[hyperobjectcount].node[urlend - urlstart] = 0;
+		strcpy(hyperobjects[hyperobjectcount].file, "");
+		hyperobjects[hyperobjectcount].tagtableoffset = -1;
+		hyperobjects[hyperobjectcount].nodelen=strlen(hyperobjects[hyperobjectcount].node);
+		hyperobjects[hyperobjectcount].filelen=strlen(hyperobjects[hyperobjectcount].file);
+		hyperobjectcount++;
+	}
+	if (initialhyperobjectcount != hyperobjectcount)
+		sort_hyperlinks_from_current_line(initialhyperobjectcount, hyperobjectcount);
+	if (buf)
+	{
+		xfree(buf);
+		buf = 0;
+	}
+}

Deleted: pinfo/branches/cxx/src/keyboard.c

Copied: pinfo/branches/cxx/src/keyboard.cxx (from rev 30, pinfo/branches/cxx/src/keyboard.c)

Deleted: pinfo/branches/cxx/src/mainfunction.c

Copied: pinfo/branches/cxx/src/mainfunction.cxx (from rev 30, pinfo/branches/cxx/src/mainfunction.c)
===================================================================
--- pinfo/branches/cxx/src/mainfunction.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/mainfunction.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,1247 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+#include "common_includes.h"
+
+RCSID("$Id$")
+
+#include <ctype.h>
+
+#ifndef MIN
+#define        MIN(a,b)(((a)<(b))?(a):(b))
+#endif
+
+void rescan_cursor();	/* set the cursor to 1st item on visible screen */
+void next_infomenu();	/* go to the next menu item for sequential reading */
+int getnodeoffset(int tag_table_pos, int *Indstart);	/* get node offset in file */
+
+int aftersearch = 0;
+/*
+ * this flag is turned on when the engine receives a simulated `key.back',
+ * caused by the sequential auto-pgdn reading code
+ */
+int toggled_by_menu = 0;
+long pos, cursor, infomenu, infocolumn=0;
+
+WorkRVal
+work(char ***message, char **type, long *lines, FILE * id, int tag_table_pos)
+{
+#define Message	(*message)
+#define Lines	(*lines)
+#define Type	(*type)
+	static WorkRVal rval =
+	{0, 0};
+	FILE *pipe;
+	int i, fileoffset, j;
+	int indirectstart = -1;
+	int cursorchanged = 0;
+	int key = 0;
+	int return_value;
+	int statusline = FREE;
+	char *token, *tmp;
+	if (rval.file)		/* if the static variable was allocated, free it */
+	{
+		xfree(rval.file);
+		rval.file = 0;
+	}
+	if (rval.node)
+	{
+		xfree(rval.node);
+		rval.node = 0;
+	}
+
+	pos = 1, cursor = 0, infomenu = -1;	/* default position, and selected number */
+
+#ifdef getmaxyx
+	getmaxyx(stdscr, maxy, maxx);	/* initialize maxx, maxy */
+#else
+	maxx = 80;
+	maxy = 25;
+#endif /*  getmaxyx */
+	/* free memory allocated previously by hypertext links */
+	freelinks();
+	for (i = 1; i < Lines; i++)	/* initialize node-links for every line */
+	{
+		initializelinks(Message[i], Message[i + 1], i);
+	}
+	initializelinks(Message[Lines], "", Lines);
+
+	next_infomenu();		/* infomenu will remain -1 if it's the last pos, or if there's no menu item */
+
+	if (npos != -1)
+		pos = npos;			/* set eventual history pos */
+
+	/* if we're in a node found using 's'earch function. */
+	if (aftersearch)
+	{
+		pos = aftersearch;	/* set pos to the found position */
+		/*      aftersearch=0;  * don't reset this--we want to know if we mus highlight something */
+	}
+
+	if (ncursor != -1)
+	{
+		cursor = ncursor;		/* set eventual cursor pos  */
+		infomenu = nmenu;		/* same with last sequential reading menu pos */
+	}
+	else
+	{
+		rescan_cursor();		/* scan for cursor position */
+	}
+	if (toggled_by_menu)		/* this node will not be shown to the user--it shouldn't go to history */
+		dellastinfohistory();	/* delete the history entry for this node--it's not even seen by the user */
+	npos = -1;			/* turn off the `next-time' pos/cursor modifiers */
+	ncursor = -1;
+	nmenu = -1;
+	addtopline(Type,infocolumn);
+	while (1)
+	{
+		/*
+		 * read key, and show screen only if there is nothing in the input
+		 * buffer.  Otherwise the scrolling would be too slow.
+		 */
+		nodelay(stdscr, TRUE);
+		key = pinfo_getch();
+		if (key == ERR)
+		{
+			if (statusline == FREE)
+				showscreen(Message, Type, Lines, pos, cursor,infocolumn);
+			waitforgetch();
+			key = pinfo_getch();
+		}
+		nodelay(stdscr, FALSE);
+		statusline = FREE;
+		if (winchanged)		/* SIGWINCH */
+		{
+			handlewinch();
+			winchanged = 0;
+			addtopline(Type,infocolumn);
+			key = pinfo_getch();
+		}
+		/***************************** keyboard handling ****************************/
+		if (key != 0)
+		{
+			if ((key == keys.print_1) ||
+					(key == keys.print_2))
+			{
+				if (yesno(_("Are you sure to print?"), 0) == 1)
+					printnode(message, lines);
+			}
+			/*==========================================================================*/
+			if ((key == keys.pgdn_auto_1) ||
+					(key == keys.pgdn_auto_2) ||
+					(toggled_by_menu))
+			{
+				int wastoggled = toggled_by_menu;
+				toggled_by_menu = 0;
+				/* if hyperobject type <= 1, then we have a menu */
+				if ((pos >= Lines -(maxy - 2)) ||(wastoggled))
+				{
+					if ((infomenu != -1) &&(!wastoggled))
+					{
+						cursor = infomenu;
+						key = keys.followlink_1;	/* the handler for keys.followlink must be bellow this statement! */
+					}
+					else
+						/* we shouldn't select a menu item if this node is called via `up:' from bottom, or if there is no menu */
+					{
+						char *typestr = strdup(Type);
+						getnextnode(Type, typestr);
+						if (strcmp(typestr, ERRNODE) != 0)
+						{
+							key = keys.nextnode_1;
+						}
+						else
+						{
+							getnodename(Type, typestr);
+							if (strcmp(FirstNodeName, typestr) != 0)	/* if it's not end of all menus */
+							{
+								if (wastoggled)	/* if we're in the temporary called up node */
+									toggled_by_menu = KILL_HISTORY;
+								else	/* if we are calling the up node from non-temporary bottom node */
+									toggled_by_menu = KEEP_HISTORY;
+								key = keys.upnode_1;
+								ungetch(KEY_NOTHING);
+							}
+						}	/* end: else if nextnode==ERRNODE */
+					}		/* end: if we shouldn't select a menu item */
+				}		/* end: if position is right */
+			}
+			/*==========================================================================*/
+			if ((key == keys.goline_1) ||
+					(key == keys.goline_2))
+			{
+				long newpos;
+				attrset(bottomline);	/* read user's value */
+				move(maxy - 1, 0);
+				echo();
+				curs_set(1);
+				token = getstring(_("Enter line: "));
+				curs_set(0);
+				noecho();
+				move(maxy - 1, 0);
+				myclrtoeol();
+				attrset(normal);
+				if (token)	/*
+							 * convert string to long.
+							 * careful with nondigit strings.
+							 */
+				{
+					int digit_val = 1;
+					for (i = 0; token[i] != 0; i++)
+					{
+						if (!isdigit(token[i]))
+							digit_val = 0;
+					}
+					if (digit_val)	/* go to specified line */
+					{
+						newpos = atol(token);
+						newpos -=(maxy - 1);
+						if ((newpos > 0) &&(newpos < Lines -(maxy - 2)))
+							pos = newpos;
+						else if ((newpos > 0) &&((Lines -(maxy - 2)) > 0))
+							pos = Lines -(maxy - 2);
+						else
+							pos = 1;
+					}
+					xfree(token);
+					token = 0;
+				}
+			}
+			/*==========================================================================*/
+			if ((key == keys.shellfeed_1) ||
+					(key == keys.shellfeed_2))
+			{
+				/* get command name */
+				attrset(bottomline);
+				move(maxy - 1, 0);
+				echo();
+				curs_set(1);
+				token = getstring(_("Enter command: "));
+				noecho();
+				move(maxy - 1, 0);
+				myclrtoeol();
+				attrset(normal);
+
+				myendwin();
+				system("clear");
+				pipe = popen(token, "w");	/* open pipe */
+				if (pipe != NULL)
+				{
+					for (i = 1; i <= Lines; i++)	/* and flush the msg to stdin */
+						fprintf(pipe, "%s", Message[i]);
+					pclose(pipe);
+					getchar();
+				}
+				doupdate();
+				curs_set(0);
+				if (pipe == NULL)
+					mvaddstr(maxy - 1, 0, _("Operation failed..."));
+				xfree(token);
+				token = 0;
+			}
+			/*==========================================================================*/
+			if ((key == keys.dirpage_1) ||
+					(key == keys.dirpage_2))
+			{
+				rval.file = (char*)malloc(10);
+				strcpy(rval.file, "dir");
+				rval.node = (char*)malloc(2);
+				strcpy(rval.node, "");
+				aftersearch = 0;
+				return rval;
+			}
+			/*==========================================================================*/
+			if ((key == keys.refresh_1) ||
+					(key == keys.refresh_2))
+			{
+				myendwin();
+				doupdate();
+				refresh();
+				curs_set(0);
+			}
+			/*==========================================================================*/
+			if ((key == keys.totalsearch_1) ||	/* search in all nodes later than this one */
+					(key == keys.totalsearch_2))
+			{
+				int tmpaftersearch = aftersearch;
+				indirectstart = -1;
+				move(maxy - 1, 0);
+				attrset(bottomline);
+				echo();
+				curs_set(1);
+				if (!searchagain.search)	/* if searchagain key wasn't hit */
+				{
+					token = getstring(_("Enter regexp: "));	/* get the token */
+					strcpy(searchagain.lastsearch, token);	/* and save it to searchagain buffer */
+					/*
+					 * give a hint, which key to ungetch to call this procedure
+					 * by searchagain
+					 */
+					searchagain.type = key;
+				}
+				else /* it IS searchagain */
+				{
+					token = (char*)xmalloc(strlen(searchagain.lastsearch) + 1);
+					/* allocate space for token */
+					strcpy(token, searchagain.lastsearch);
+					/* copy the token from searchagain buffer */
+					searchagain.search = 0;
+					/* reset the searchagain swith(until it's set again
+					   by the keys.searchagain key handler) */
+				}
+				if (strlen(token) == 0)
+				{
+					xfree(token);
+					goto skip_search;
+				}
+				curs_set(0);
+				noecho();
+				attrset(normal);
+
+				/* Calculate current info file offset...  */
+				fileoffset = 0;
+				for (i = 1; i <= pos + 1; i++)	/* count the length of curnode */
+					fileoffset += strlen(Message[i]);
+				fileoffset += strlen(Type);	/* add also header length */
+
+				fileoffset += getnodeoffset(tag_table_pos, &indirectstart);	/* also load the variable indirectstart */
+
+				/* Searching part...  */
+				aftersearch = 0;
+
+				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+				return_value = -1;
+				if (indirect)	/* the info is of indirect type; we'll search through several files */
+				{
+					FILE *fd;
+					long tokenpos;
+					long starttokenpos;
+					long filelen;
+					for (j = indirectstart; j <= IndirectEntries; j++)
+					{
+						fd = openinfo(indirect[j].filename, 1);	/* get file
+																	 * length. */
+						fseek(fd, 0, SEEK_END);
+						filelen = ftell(fd);
+
+						/*
+						 * seek to the beginning of search area. At the first
+						 * time it is `fileoffset', then it is the first node's
+						 * offset
+						 */
+						if (j == indirectstart)
+
+							fseek(fd, fileoffset, SEEK_SET);
+						else
+							fseek(fd, FirstNodeOffset, SEEK_SET);
+						starttokenpos = ftell(fd);
+
+						tmp = (char*)xmalloc(filelen - starttokenpos + 10);	/* read data */
+						fread(tmp, 1, filelen - starttokenpos, fd);
+						tmp[filelen - starttokenpos + 1] = 0;
+
+						tokenpos = regexp_search(token, tmp);	/* search */
+
+						if (tokenpos != -1)	/* if something was found */
+						{
+							/*
+							 * add the offset of the part of file, which wasn't
+							 * read to the memory
+							 */
+							tokenpos += starttokenpos;
+							{	/* local scope for tmpvar, matched */
+								int tmpvar = 0, matched = 0;
+								tag_table[0].offset = 0;
+								for (i = TagTableEntries; i >= 1; i--)
+								{
+									if ((tag_table[i].offset > tag_table[tmpvar].offset) &&
+											((tag_table[i].offset - indirect[j].offset + FirstNodeOffset) <= tokenpos))
+									{
+										return_value = i;
+										tmpvar = i;
+										matched = 1;
+									}
+								}
+							}
+							/* this means, that indirect entry was found.  */
+							if (return_value != -1)
+							{
+								fseek(fd, tag_table[return_value].offset - indirect[j].offset + FirstNodeOffset, SEEK_SET);
+								/* seek to the found node offset */
+								while (fgetc(fd) != INFO_TAG);
+								fgetc(fd);	/* skip newline */
+
+								aftersearch = 1;
+
+								/*
+								 * count, how many lines stands befor the token
+								 * line.
+								 */
+								while (ftell(fd) < tokenpos)
+								{
+									int chr = fgetc(fd);
+									if (chr == '\n')
+										aftersearch++;
+									else if (chr == EOF)
+										break;
+								}
+								/*
+								 * the number ofline where a token is found, is
+								 * now in the variable `aftersearch'
+								 */
+								if (aftersearch > 1)
+									aftersearch--;
+								else
+									aftersearch = 1;
+							}	/* end: if (indirect entry was found) */
+							if (aftersearch)	/* if something was found */
+							{
+								if (tmp)	/* free tmp buffer */
+								{
+									xfree(tmp);
+									tmp = 0;
+								}
+								break;
+							}
+						}	/* end: if (tokenpos) */
+					}		/* end: indirect file loop */
+					if (tmp)	/* free tmp buffer */
+					{
+						xfree(tmp);
+						tmp = 0;
+					}
+					fclose(fd);
+				}		/* end: if (indirect) */
+				else /* if not indirect */
+				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+				{
+					long filelen;
+					long filepos = ftell(id);
+					long tokenpos;
+					long starttokenpos;
+
+					fseek(id, 0, SEEK_END);	/* calculate filelength */
+					filelen = ftell(id);
+
+					/* seek at the start of search area. */
+					fseek(id, fileoffset, SEEK_SET);
+
+					/* remember the number of skipped bytes.*/
+					starttokenpos = ftell(id);
+
+					/* read data */
+					tmp = (char*)xmalloc(filelen - starttokenpos + 10);
+					fread(tmp, 1, filelen - starttokenpos, id);
+					tmp[filelen - starttokenpos + 1] = 0;
+
+					/* search */
+					tokenpos = regexp_search(token, tmp);
+
+					if (tokenpos != -1)	/* if we've found something */
+					{
+						/*
+						 * add offset of the start of search area to this token
+						 * position.
+						 */
+						tokenpos += starttokenpos;
+						{		/* local scope for tmpvar, matched */
+							int tmpvar = 0, matched = 0;
+							tag_table[0].offset = 0;
+							for (i = TagTableEntries; i >= 1; i--)
+							{
+								if ((tag_table[i].offset > tag_table[tmpvar].offset) &&
+										(tag_table[i].offset <= tokenpos))
+								{
+									return_value = i;
+									tmpvar = i;
+									matched = 1;
+								}
+							}
+						}
+						/*
+						 * this means, that we've found our entry, and we're
+						 * one position too far with the `i' counter.
+						 */
+						if (return_value != -1)
+						{
+							fseek(id, tag_table[return_value].offset, SEEK_SET);
+							/* seek to the node, which holds found line */
+							while (fgetc(id) != INFO_TAG);
+							fgetc(id);	/* skip newline */
+
+							aftersearch = 1;
+							/* count lines in found node, until found line is
+							 * met. */
+							while (ftell(id) < tokenpos)
+							{
+								int chr = fgetc(id);
+								if (chr == '\n')
+									aftersearch++;
+								else if (chr == EOF)
+									break;
+							}
+							if (aftersearch > 1)
+								aftersearch--;
+							else
+								aftersearch = 1;
+							fseek(id, filepos, SEEK_SET);	/* seek to old
+															 * filepos. */
+						}
+					}		/* end: if (tokenpos) <--> token found */
+					if (tmp)	/* free tmp buffer */
+					{
+						xfree(tmp);
+						tmp = 0;
+					}
+				}		/* end: if (!indirect) */
+				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+				xfree(token);
+				token = 0;
+
+				if (!aftersearch)
+				{
+					attrset(bottomline);
+					mvaddstr(maxy - 1, 0, _("Search string not found..."));
+					statusline = LOCKED;
+				}
+
+				if (!aftersearch)
+					aftersearch = tmpaftersearch;
+
+				if (return_value != -1)
+				{
+					infohistory.pos[infohistory.length] = pos;
+					infohistory.cursor[infohistory.length] = cursor;
+					infohistory.menu[infohistory.length] = infomenu;
+					rval.node = (char*)xmalloc(strlen(tag_table[return_value].nodename) + 1);
+					strcpy(rval.node, tag_table[return_value].nodename);
+					rval.file = (char*)xmalloc(1);
+					rval.file[0] = 0;
+					return rval;
+				}
+			}			/* end: if key_totalsearch */
+			/*==========================================================================*/
+			if ((key == keys.search_1) ||		/* search in current node */
+					(key == keys.search_2))
+			{
+				int success = 0;
+				move(maxy - 1, 0);
+				attrset(bottomline);
+				echo();
+				curs_set(1);
+				if (!searchagain.search)	/* searchagain handler. see totalsearch */
+				{
+					token = getstring(_("Enter regexp: "));
+					strcpy(searchagain.lastsearch, token);
+					searchagain.type = key;
+				}
+				else
+				{
+					token = (char*)xmalloc(strlen(searchagain.lastsearch) + 1);
+					strcpy(token, searchagain.lastsearch);
+					searchagain.search = 0;
+				}		/* end of searchagain handler */
+				if (strlen(token) == 0)
+				{
+					xfree(token);
+					goto skip_search;
+				}
+				curs_set(0);
+				noecho();
+				attrset(normal);
+				/* compile the read token */
+				if (pinfo_re_comp(token) != 0)
+				{
+					/* print error message */
+					attrset(bottomline);
+					mymvhline(maxy - 1, 0, ' ', maxx);
+					move(maxy - 1, 0);
+					printw(_("Invalid regular expression;"));
+					printw(" ");
+					printw(_("Press any key to continue..."));
+					getch();
+					goto skip_search;
+					
+				}
+				/* scan for the token in the following lines.  */
+				for (i = pos + 1; i < Lines; i++)
+				{
+					tmp = (char*)xmalloc(strlen(Message[i]) + strlen(Message[i + 1]) + 2);
+					/*
+					 * glue two following lines into one -- to find matches
+					 * split up into two lines.
+					 */
+					strcpy(tmp, Message[i]);
+					strcat(tmp, Message[i + 1]);
+					if (pinfo_re_exec(tmp))	/* execute the search command */
+					{		/* if found, enter here */
+						success = 1;
+						/* if token was found in the second line, make pos=i+1.  */
+						if (pinfo_re_exec(Message[i + 1]))
+							pos = i + 1;
+						else /* othwerwise, pos=i. This happens when we havesplit expression. */
+							pos = i;
+						xfree(tmp);	/* free tmp buffer */
+						tmp = 0;
+						aftersearch = 1;
+						break;
+					}
+					else /* nothing found */
+					{
+						xfree(tmp);	/* free tmp buffer */
+						tmp = 0;
+					}
+				}
+				if (!success)
+				{
+					attrset(bottomline);
+					mvaddstr(maxy - 1, 0, _("Search string not found..."));
+					statusline = LOCKED;
+				}
+				xfree(token);	/* free user's search token */
+				token = 0;
+				rescan_cursor();	/* rescan cursor position in the new place */
+			}
+skip_search:
+			/*==========================================================================*/
+			if ((key == keys.search_again_1) ||	/* search again */
+					(key == keys.search_again_2))
+			{
+				if (searchagain.type != 0)	/* if a search was made before */
+				{
+					searchagain.search = 1;	/* mark, that search routines should *
+											 * use the searchagain token value   */
+					ungetch(searchagain.type);	/* ungetch the proper *
+												 * search key         */
+				}
+			}
+			/*==========================================================================*/
+
+			if ((key == keys.goto_1) ||	/* goto node */
+					(key == keys.goto_2))
+			{
+				return_value = -1;
+				move(maxy - 1, 0);
+				attrset(bottomline);
+				curs_set(1);
+				token = getstring(_("Enter node name: "));	/* read user's wish */
+				curs_set(0);
+				noecho();
+				attrset(normal);
+				for (i = 1; i <= TagTableEntries; i++)
+				{
+					/* if the name was found in the tag table */
+					if (strcmp(token, tag_table[i].nodename) == 0)
+					{
+						return_value = i;
+						break;
+					}
+				}
+				if (return_value != -1)	/* if the name was in tag table */
+				{
+					xfree(token);
+					token = 0;
+					infohistory.pos[infohistory.length] = pos;
+					infohistory.cursor[infohistory.length] = cursor;
+					infohistory.menu[infohistory.length] = infomenu;
+					rval.node = (char*)xmalloc(strlen(tag_table[return_value].nodename) + 1);
+					strcpy(rval.node, tag_table[return_value].nodename);
+					rval.file = (char*)xmalloc(1);
+					rval.file[0] = 0;
+					aftersearch = 0;
+					return rval;
+				}
+				else
+					/* if the name wasn't in tag table */
+				{
+					/*
+					 * scan for filename: filenames may be specified in format:
+					 * (file)node
+					 */
+					char *gotostartptr = strchr(token, '(');
+					if (gotostartptr)	/* if there was a `(' */
+					{
+						char *gotoendptr = strchr(token, ')');	/* search for `)' */
+						/* if they're in the right order...  */
+						if (gotoendptr > gotostartptr)
+						{
+							rval.file = (char*)xmalloc(gotoendptr - gotostartptr + 1);
+							strncpy(rval.file, gotostartptr + 1, gotoendptr - gotostartptr - 1);
+							rval.file[gotoendptr - gotostartptr - 1] = 0;
+							gotoendptr++;
+							while (gotoendptr)	/* skip whitespaces until nodename */
+							{
+								if (*gotoendptr != ' ')
+									break;
+								gotoendptr++;
+							}	/* skip spaces */
+							rval.node = (char*)xmalloc(strlen(gotoendptr) + 1);
+							strcpy(rval.node, gotoendptr);
+							xfree(token);
+							token = 0;
+							aftersearch = 0;
+							return rval;
+						}
+					}
+					/* handle the `file.info' format of crossinfo goto. */
+					else if (strstr(token, ".info"))
+					{
+						rval.file = (char*)xmalloc(strlen(token) + 1);
+						strcpy(rval.file, token);
+						xfree(token);
+						token = 0;
+						rval.node = (char*)xmalloc(5);
+						strcpy(rval.node, "");
+						aftersearch = 0;
+						return rval;
+					}
+					else /* node not found */
+					{
+						attrset(bottomline);
+						mymvhline(maxy - 1, 0, ' ', maxx);
+						move(maxy - 1, 0);
+						printw(_("Node %s not found"), token);
+						attrset(normal);
+						move(0, 0);
+					}
+				}
+				statusline = LOCKED;
+				xfree(token);
+				token = 0;
+			}
+			/*==========================================================================*/
+			if ((key == keys.prevnode_1) ||	/* goto previous node */
+					(key == keys.prevnode_2))
+			{
+				token = (char*)xmalloc(strlen(Type));
+				getprevnode(Type, token);
+				return_value = gettagtablepos(token);
+				xfree(token);
+				token = 0;
+				if (return_value != -1)
+				{
+					infohistory.pos[infohistory.length] = pos;
+					infohistory.cursor[infohistory.length] = cursor;
+					infohistory.menu[infohistory.length] = infomenu;
+					rval.node = (char*)xmalloc(strlen(tag_table[return_value].nodename) + 1);
+					strcpy(rval.node, tag_table[return_value].nodename);
+					rval.file = (char*)xmalloc(1);
+					rval.file[0] = 0;
+					aftersearch = 0;
+					return rval;
+				}
+			}
+			/*==========================================================================*/
+			if ((key == keys.nextnode_1) ||	/* goto next node */
+					(key == keys.nextnode_2))
+			{
+				token = (char*)xmalloc(strlen(Type));
+				getnextnode(Type, token);
+				return_value = gettagtablepos(token);
+				xfree(token);
+				token = 0;
+				if (return_value != -1)
+				{
+					infohistory.pos[infohistory.length] = pos;
+					infohistory.cursor[infohistory.length] = cursor;
+					infohistory.menu[infohistory.length] = infomenu;
+					rval.node = (char*)xmalloc(strlen(tag_table[return_value].nodename) + 1);
+					strcpy(rval.node, tag_table[return_value].nodename);
+					rval.file = (char*)xmalloc(1);
+					rval.file[0] = 0;
+					aftersearch = 0;
+					return rval;
+				}
+			}
+			/*==========================================================================*/
+			if ((key == keys.upnode_1) ||		/* goto up node */
+					(key == keys.upnode_2))
+			{
+				token = (char*)xmalloc(strlen(Type));
+				getupnode(Type, token);
+				if (strncmp(token, "(dir)", 5) == 0)
+				{
+					ungetch(keys.dirpage_1);
+				}
+				return_value = gettagtablepos(token);
+				xfree(token);
+				token = 0;
+				if (return_value != -1)
+				{
+					if (toggled_by_menu == KEEP_HISTORY)
+					{
+						infohistory.pos[infohistory.length] = pos;
+						infohistory.cursor[infohistory.length] = cursor;
+						infohistory.menu[infohistory.length] = infomenu;
+					}
+					rval.node = (char*)xmalloc(strlen(tag_table[return_value].nodename) + 1);
+					strcpy(rval.node, tag_table[return_value].nodename);
+					rval.file = (char*)xmalloc(1);
+					rval.file[0] = 0;
+					aftersearch = 0;
+					return rval;
+				}
+			}
+			/*==========================================================================*/
+			if ((key == keys.twoup_1) || (key == keys.twoup_2))
+			{
+				ungetch(keys.up_1);
+				ungetch(keys.up_1);
+			}
+			/*==========================================================================*/
+			if ((key == keys.up_1) ||
+					(key == keys.up_2))
+			{
+				cursorchanged = 0;
+				if (cursor != -1)	/* if we must handle cursor... */
+				{
+					if ((cursor > 0) &&(hyperobjectcount))	/* if we really must handle it ;) */
+						/*
+						 * look if there's a cursor(link) pos available above,
+						 * and if it is visible now.
+						 */
+						for (i = cursor - 1; i >= 0; i--)
+						{
+							if ((hyperobjects[i].line >= pos) &&
+									(hyperobjects[i].line < pos +(maxy - 1)))
+							{
+								/* don't play with `highlight' objects */
+								if (hyperobjects[i].type < HIGHLIGHT)
+								{
+									cursor = i;
+									cursorchanged = 1;
+									break;
+								}
+							}
+						}
+				}
+				if (!cursorchanged)	/* if the cursor wasn't changed */
+				{
+					if (pos > 2)	/* lower the nodepos */
+						pos--;
+					/* and scan for a hyperlink in the new line */
+					for (i = 0; i < hyperobjectcount; i++)
+					{
+						if (hyperobjects[i].line == pos)
+						{
+							if (hyperobjects[i].type < HIGHLIGHT)
+							{
+								cursor = i;
+								break;
+							}
+						}
+					}
+				}
+			}
+			/*==========================================================================*/
+			if ((key == keys.end_1) ||
+					(key == keys.end_2))
+			{
+				pos = Lines -(maxy - 2);
+				if (pos < 1)
+					pos = 1;
+				cursor = hyperobjectcount - 1;
+			}
+			/*==========================================================================*/
+			if ((key == keys.pgdn_1) ||
+					(key == keys.pgdn_2))
+			{
+				if (pos +(maxy - 2) < Lines -(maxy - 2))
+				{
+					pos +=(maxy - 2);
+					rescan_cursor();
+				}
+				else if (Lines -(maxy - 2) >= 1)
+				{
+					pos = Lines -(maxy - 2);
+					cursor = hyperobjectcount - 1;
+				}
+				else
+				{
+					pos = 1;
+					cursor = hyperobjectcount - 1;
+				}
+			}
+			/*==========================================================================*/
+			if ((key == keys.home_1) ||
+					(key == keys.home_2))
+			{
+				pos = 1;
+				rescan_cursor();
+			}
+			/*==========================================================================*/
+			if ((key == keys.pgup_1) |
+					(key == keys.pgup_2))
+			{
+				if (pos >(maxy - 2))
+					pos -=(maxy - 2);
+				else
+					pos = 1;
+				rescan_cursor();
+			}
+			/*==========================================================================*/
+			if ((key == keys.pgup_auto_1) ||
+					(key == keys.pgup_auto_2))
+			{
+				if (pos == 1)
+					ungetch(keys.upnode_1);
+			}
+			/*==========================================================================*/
+			if ((key == keys.twodown_1) ||
+					(key == keys.twodown_2))	/* top+bottom line \|/ */
+			{
+				ungetch(keys.down_1);
+				ungetch(keys.down_1);
+			}
+			/*==========================================================================*/
+			if ((key == keys.down_1) ||
+					(key == keys.down_2))	/* top+bottom line \|/ */
+			{
+				cursorchanged = 0;	/* works similar to keys.up */
+				if (cursor < hyperobjectcount)
+					for (i = cursor + 1; i < hyperobjectcount; i++)
+					{
+						if ((hyperobjects[i].line >= pos) &&
+								(hyperobjects[i].line < pos +(maxy - 2)))
+						{
+							if (hyperobjects[i].type < HIGHLIGHT)
+							{
+								cursor = i;
+								cursorchanged = 1;
+								break;
+							}
+						}
+					}
+				if (!cursorchanged)
+				{
+					if (pos <= Lines -(maxy - 2))
+						pos++;
+					for (i = cursor + 1; i < hyperobjectcount; i++)
+					{
+						if ((hyperobjects[i].line >= pos) &&
+								(hyperobjects[i].line < pos +(maxy - 2)))
+						{
+							if (hyperobjects[i].type < HIGHLIGHT)
+							{
+								cursor = i;
+								cursorchanged = 1;
+								break;
+							}
+						}
+					}
+				}
+			}
+			/*==========================================================================*/
+			if ((key == keys.top_1) ||
+					(key == keys.top_2))
+			{
+				infohistory.pos[infohistory.length] = pos;
+				infohistory.cursor[infohistory.length] = cursor;
+				infohistory.menu[infohistory.length] = infomenu;
+				rval.node = (char*)xmalloc(strlen(FirstNodeName) + 1);
+				strcpy(rval.node, FirstNodeName);
+				rval.file = (char*)xmalloc(1);
+				rval.file[0] = 0;
+				aftersearch = 0;
+				return rval;
+			}
+			/*==========================================================================*/
+			if ((key == keys.back_1) ||
+					(key == keys.back_2))
+			{
+				if (infohistory.length > 1)
+				{
+					dellastinfohistory();	/* remove history entry for this node */
+					/* now we deal with the previous node history entry */
+
+					rval.node = (char*)xmalloc(strlen(infohistory.node[infohistory.length]) + 1);
+					strcpy(rval.node, infohistory.node[infohistory.length]);
+					rval.file = (char*)xmalloc(strlen(infohistory.file[infohistory.length]) + 1);
+					strcpy(rval.file, infohistory.file[infohistory.length]);
+
+					npos = infohistory.pos[infohistory.length];
+					ncursor = infohistory.cursor[infohistory.length];
+					nmenu = infohistory.menu[infohistory.length];
+					dellastinfohistory();	/* remove history entry for previous node */
+					aftersearch = 0;
+					return rval;
+				}
+			}
+			/*==========================================================================*/
+			if ((key == keys.followlink_1) ||
+					(key == keys.followlink_2))
+			{
+				infohistory.pos[infohistory.length] = pos;
+				infohistory.cursor[infohistory.length] = cursor;
+				infohistory.menu[infohistory.length] = infomenu;
+				if (!toggled_by_menu)
+					infohistory.menu[infohistory.length] = cursor;
+				if ((cursor >= 0) &&(cursor < hyperobjectcount))
+					if ((hyperobjects[cursor].line >= pos) &&
+							(hyperobjects[cursor].line < pos +(maxy - 2)) ||
+							(toggled_by_menu))
+					{
+						toggled_by_menu = 0;
+						if (hyperobjects[cursor].type < 4)	/* normal info link */
+						{
+							rval.node = (char*)xmalloc(strlen(hyperobjects[cursor].node) + 1);
+							strcpy(rval.node, hyperobjects[cursor].node);
+							rval.file = (char*)xmalloc(strlen(hyperobjects[cursor].file) + 1);
+							strcpy(rval.file, hyperobjects[cursor].file);
+							aftersearch = 0;
+							return rval;
+						}
+						else if (hyperobjects[cursor].type < HIGHLIGHT)	/* we deal with an url */
+						{
+							if (hyperobjects[cursor].type == 4)	/* http */
+							{
+								char *tempbuf = (char*)xmalloc(strlen(hyperobjects[cursor].node) + strlen(httpviewer) + 10);
+								strcpy(tempbuf, httpviewer);
+								strcat(tempbuf, " ");
+								strcat(tempbuf, hyperobjects[cursor].node);
+								myendwin();
+								system(tempbuf);
+								doupdate();
+								xfree(tempbuf);
+							}
+							else if (hyperobjects[cursor].type == 5)	/* ftp */
+							{
+								char *tempbuf = (char*)xmalloc(strlen(hyperobjects[cursor].node) + strlen(ftpviewer) + 10);
+								strcpy(tempbuf, ftpviewer);
+								strcat(tempbuf, " ");
+								strcat(tempbuf, hyperobjects[cursor].node);
+								myendwin();
+								system(tempbuf);
+								doupdate();
+								xfree(tempbuf);
+							}
+							else if (hyperobjects[cursor].type == 6)	/* mail */
+							{
+								char *tempbuf = (char*)xmalloc(strlen(hyperobjects[cursor].node) + strlen(maileditor) + 10);
+								strcpy(tempbuf, maileditor);
+								strcat(tempbuf, " ");
+								strcat(tempbuf, hyperobjects[cursor].node);
+								myendwin();
+								system("clear");
+								system(tempbuf);
+								doupdate();
+								xfree(tempbuf);
+							}
+						}
+					}
+			}
+			/*==========================================================================*/
+			if ((key == keys.left_1) ||(key == keys.left_2))
+			{
+				if (infocolumn>0) infocolumn--;
+				addtopline(Type,infocolumn);
+			}
+			/*==========================================================================*/
+			if ((key == keys.right_1) ||(key == keys.right_2))
+			{
+				infocolumn++;
+				addtopline(Type,infocolumn);
+			}
+			/*==========================================================================*/
+			/**************************** end of keyboard handling **********************/
+			/******************************** mouse handler *****************************/
+#ifdef NCURSES_MOUSE_VERSION
+			if (key == KEY_MOUSE)
+			{
+				MEVENT mouse;
+				int done = 0;
+				getmouse(&mouse);
+				if (mouse.bstate == BUTTON1_CLICKED)
+				{
+					if ((mouse.y > 0) &&(mouse.y < maxy - 1))
+					{
+						for (i = cursor; i > 0; i--)
+						{
+							if (hyperobjects[i].line == mouse.y + pos - 1)
+							{
+								if (hyperobjects[i].col <= mouse.x - 1)
+								{
+									if (hyperobjects[i].col + strlen(hyperobjects[i].node) + strlen(hyperobjects[i].file) >= mouse.x - 1)
+									{
+										if (hyperobjects[i].type < HIGHLIGHT)
+										{
+											cursor = i;
+											done = 1;
+											break;
+										}
+									}
+								}
+							}
+						}
+						if (!done)
+							for (i = cursor; i < hyperobjectcount; i++)
+							{
+								if (hyperobjects[i].line == mouse.y + pos - 1)
+								{
+									if (hyperobjects[i].col <= mouse.x - 1)
+									{
+										if (hyperobjects[i].col + strlen(hyperobjects[i].node) + strlen(hyperobjects[i].file) >= mouse.x - 1)
+										{
+											if (hyperobjects[i].type < HIGHLIGHT)
+											{
+												cursor = i;
+												done = 1;
+												break;
+											}
+										}
+									}
+								}
+							}
+					}		/* end: if (mouse.y not on top/bottom line) */
+					else if (mouse.y == 0)
+						ungetch(keys.up_1);
+					else if (mouse.y == maxy - 1)
+						ungetch(keys.down_1);
+				}		/* end: button clicked */
+				if (mouse.bstate == BUTTON1_DOUBLE_CLICKED)
+				{
+					if ((mouse.y > 0) &&(mouse.y < maxy - 1))
+					{
+						for (i = cursor; i >= 0; i--)
+						{
+							if (hyperobjects[i].line == mouse.y + pos - 1)
+							{
+								if (hyperobjects[i].col <= mouse.x - 1)
+								{
+									if (hyperobjects[i].col + strlen(hyperobjects[i].node) + strlen(hyperobjects[i].file) >= mouse.x - 1)
+									{
+										if (hyperobjects[i].type < HIGHLIGHT)
+										{
+											cursor = i;
+											done = 1;
+											break;
+										}
+									}
+								}
+							}
+						}
+						if (!done)
+							for (i = cursor; i < hyperobjectcount; i++)
+							{
+								if (hyperobjects[i].line == mouse.y + pos - 1)
+								{
+									if (hyperobjects[i].col <= mouse.x - 1)
+									{
+										if (hyperobjects[i].col + strlen(hyperobjects[i].node) + strlen(hyperobjects[i].file) >= mouse.x - 1)
+										{
+											if (hyperobjects[i].type < HIGHLIGHT)
+											{
+												cursor = i;
+												done = 1;
+												break;
+											}
+										}
+									}
+								}
+							}
+						if (done)
+							ungetch(keys.followlink_1);
+					}		/* end: if (mouse.y not on top/bottom line) */
+					else if (mouse.y == 0)
+						ungetch(keys.pgup_1);
+					else if (mouse.y == maxy - 1)
+						ungetch(keys.pgdn_1);
+				}		/* end: button doubleclicked */
+			}
+#endif
+			/*****************************************************************************/
+		}
+		if ((key == keys.quit_2) ||(key == keys.quit_1))
+		{
+			if (!ConfirmQuit)
+				break;
+			else
+			{
+				if (yesno(_("Are you sure to quit?"), QuitConfirmDefault))
+					break;
+			}
+		}
+	}
+	aftersearch = 0;
+	return rval;
+}
+
+void
+next_infomenu()
+{
+	int i;
+	if (hyperobjectcount == 0)
+	{
+		infomenu = -1;
+		return;
+	}
+	for (i = infomenu + 1; i < hyperobjectcount; i++)
+	{
+		if (hyperobjects[i].type <= 1)	/* menu item */
+		{
+			infomenu = i;
+			return;
+		}
+	}
+	infomenu = -1;		/* no menuitem left is found */
+}
+
+void
+rescan_cursor()
+{
+	int i;
+	for (i = 0; i < hyperobjectcount; i++)
+	{
+		if ((hyperobjects[i].line >= pos) &&
+				(hyperobjects[i].line < pos +(maxy - 2)))
+		{
+			if (hyperobjects[i].type < HIGHLIGHT)
+			{
+				cursor = i;
+				break;
+			}
+		}
+	}
+}
+
+int
+getnodeoffset(int tag_table_pos, int *Indstart)	/* count node offset in file */
+{
+#define indirectstart	(*Indstart)
+	int i, fileoffset = 0;
+	if (indirect)
+	{
+		for (i = IndirectEntries; i >= 1; i--)
+		{
+			if (indirect[i].offset <= tag_table[tag_table_pos].offset)
+			{
+				fileoffset +=(tag_table[tag_table_pos].offset - indirect[i].offset + FirstNodeOffset);
+				indirectstart = i;
+				break;
+			}
+		}
+	}
+	else
+	{
+		fileoffset +=(tag_table[tag_table_pos].offset - 2);
+	}
+	return fileoffset;
+#undef indirectstart
+}

Deleted: pinfo/branches/cxx/src/manual.c

Copied: pinfo/branches/cxx/src/manual.cxx (from rev 30, pinfo/branches/cxx/src/manual.c)
===================================================================
--- pinfo/branches/cxx/src/manual.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/manual.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,1920 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+#include "common_includes.h"
+
+RCSID("$Id$")
+
+#include <ctype.h>
+#include <sys/stat.h>
+
+#define HTTPSECTION 100
+#define FTPSECTION 101
+#define MAILSECTION 102
+
+/* check if a char is a hyphen character */
+int ishyphen(unsigned char ch);
+/* load manual */
+void loadmanual(FILE * id);
+/* handle keyboard */
+int manualwork();
+void rescan_selected();	/* scan for potential link to select on
+							   viewed manual page */
+/* self explanatory */
+void showmanualscreen();
+/* mvaddstr with bold/italic */
+void mvaddstr_manual(int y, int x, char *str);
+/* adds highlights to a painted screen */
+void add_highlights();
+/* strips line from formatting characters */
+void strip_manual(char *buf);
+/*
+ * Initialize links in a line .  Links are entries of form reference(section),
+ * and are stored in `manuallinks' var, described bellow.
+ */
+void man_initializelinks(char *line, int carry);
+int is_in_manlinks(char *in, char *find);
+
+void printmanual(char **Message, long Lines);
+
+/* line by line stored manual */
+char **manual = 0;
+/* number of lines in manual */
+int ManualLines = 0;
+int selected = -1;		/* number of selected link(offset in 'manuallinks',
+						   bellow) */
+int manualpos = 0;		/* number of the first line, which is painted on
+						   screen */
+
+int manualcol = 0;		/* the first displayed column of manpage--
+						   for moving the screen left/right */
+
+int manual_aftersearch = 0;	/* this is set if man page is now after search
+							   operation */
+int manwidthChanged = 0;	/* this flag indicates whether the env variable
+							   $MANWIDTH was changed by pinfo */
+
+typedef struct
+{
+	/* name of a manual */
+	char name[256];
+	/* section */
+	char sect[32];
+	/* what was last selected on this page */
+	int selected;
+	/* what was the last manualpos */
+	int pos;
+}
+manhistory;			/*
+					 * type for the `lastread' history entries, when viewing
+					 * man pages.
+					 */
+
+/* manual lastread history */
+manhistory *manualhistory = 0;
+/* length of the above table - 1 */
+int manualhistorylength = 0;
+
+/* this structure describes a hyperlink in manual viewer */
+typedef struct
+{			/* struct for hypertext references */
+	int line;		/* line of the manpage, where the reference is */
+	/* column of that line */
+	int col;
+	/* name of the reference */
+	char *name;
+	/* section of the reference */
+	char section[32];
+	int section_mark;
+	/* determine whether there is a hyphen above */
+	int carry;
+}
+manuallink;
+
+/* a set of manual references of man page */
+manuallink *manuallinks = 0;
+
+/* number of found manual references in man page */
+int ManualLinks = 0;
+
+/* semaphore for checking if it's a history(left arrow) call */
+int historical = 0;
+
+
+void
+/* free buffers allocated by current man page */
+manual_free_buffers()
+{
+	int i;
+	/* first free previously allocated memory */
+	/* for the manual itself... */
+	if (manual)
+	{
+		for (i = 0; i <= ManualLines; i++)
+		{
+			xfree(manual[i]);
+		}
+		xfree(manual);
+		manual = 0;
+		ManualLines = 0;
+	}
+	/* ...and for the list of manual hypertext */
+	if (manuallinks)
+	{				/* links */
+		for (i = 0; i < ManualLinks; i++)
+		{
+			xfree(manuallinks[i].name);
+		}
+		xfree(manuallinks);
+		manuallinks = 0;
+		ManualLinks = 0;
+		selected = -1;
+	}
+}
+
+/* initialize history variables for manual pages.  */
+void
+set_initial_history(char *name)
+{
+	int len = strlen(name), i;
+	char *name1 = strdup(name);
+
+	/* one object of array */
+	manualhistory = (manhistory*)xmalloc(sizeof(manhistory));
+	/* filter trailing spaces */
+	while ((len > 1) &&(isspace(name1[len - 1])))
+	{
+		name1[len - 1] = 0;
+		len--;
+	}
+	i = len;
+	/* find the beginning of the last token */
+	for (i = len - 1;(i > 0) &&(!isspace(name1[i])); i--);
+
+	/* if we've found space, then we move to the first nonspace character */
+	if (i > 0)
+		i++;
+
+	/* filename->name */
+	strcpy(manualhistory[0].name, &name1[i]);
+	/* section unknown */
+	strcpy(manualhistory[0].sect, "");
+	/* selected unknown */
+	manualhistory[0].selected = -1;
+	/* pos=0 */
+	manualhistory[0].pos = 0;
+	free(name1);
+}
+
+/* construct man name; take care about carry */
+void
+construct_manualname(char *buf, int which)
+{
+	if (!manuallinks[which].carry)
+	{
+		/* workaround for names starting with '(' */
+		if (manuallinks[which].name[0] == '(') strcpy(buf, manuallinks[which].name + 1);
+		else strcpy(buf, manuallinks[which].name);
+		return;
+	}
+	else
+	{
+		/* normal manual reference */
+		if (manuallinks[which].section_mark < HTTPSECTION)
+		{
+			char *base = (char*)xmalloc(1024);
+			char *ptr;
+			int tmppos;
+			strcpy(base, manual[manuallinks[which].line - 1]);
+			strip_manual(base);
+			ptr = base + strlen(base) - 3;
+			while (((isalpha(*ptr)) ||(*ptr == '.') ||(*ptr == '_')) &&(ptr > base))
+				ptr--;
+			/* workaround for man pages with leading '(' see svgalib man pages */
+			if (*ptr == '(')
+				ptr++;
+			strcpy(buf, ptr);
+			tmppos = strlen(buf);
+			/* TODO: check the following statement */
+			if (tmppos > 1);
+			buf[tmppos - 2] = 0;
+			strcat(buf, manuallinks[which].name);
+			xfree(base);
+		}
+		/* url reference */
+		else
+		{
+			char *base = (char*)xmalloc(1024);
+			char *ptr, *eptr;
+			int tmppos;
+			int namelen = strlen(manuallinks[which].name);
+			strcpy(base, manual[manuallinks[which].line + 1]);
+			strip_manual(base);
+			ptr = base;
+			/* skip whitespace */
+			while (isspace(*ptr))
+				ptr++;
+			eptr = findurlend(ptr);
+			*eptr = 0;
+			strcpy(buf, manuallinks[which].name);
+			/* cut the hyphen */
+			buf[namelen - 1] = 0;
+			strcat(buf, ptr);
+			xfree(base);
+		}
+	}
+}
+
+/* this is something like main() function for the manual viewer code.  */
+int
+handlemanual(char *name)
+{
+	int return_value = 0;
+	struct stat statbuf;
+	FILE *id, *source;
+
+	char **ignored_entries;
+	char manualname[256];
+	char cmd[256];
+	char location[256];
+	char line[1025];
+	char *raw_tempfilename = 0;
+	char *apropos_tempfilename = 0;
+	char *end, *prev;
+	size_t macroline_size;
+	int ignored_items = 0, i = 0;
+	char zipped = 0;
+
+	if (tmpfilename1)
+	{
+		unlink(tmpfilename1);
+		xfree(tmpfilename1);
+	}
+	tmpfilename1 = tempnam("/tmp", NULL);
+
+#ifdef getmaxyx
+	init_curses();
+	/* if ncurses, get maxx and maxy */
+	getmaxyx(stdscr, maxy, maxx);
+	myendwin();
+	if ((!getenv("MANWIDTH")) ||(manwidthChanged))
+	{
+		/* set MANWIDTH environment variable */
+		static char tmp[24];
+		snprintf(tmp, 24, "MANWIDTH=%d", maxx);
+		putenv(tmp);
+		manwidthChanged = 1;
+	}
+#else
+	/* otherwise hardcode 80x25... */
+	maxx = 80;
+	maxy = 25;
+#endif /* getmaxyx */
+#ifdef NIETS
+	/****************************************************************************
+	 *                    Ignore macros part: BEGIN                             *
+	 * PS: Siewca: I still expect that you'll isolate it to a single procedure  *
+	 * Description(by PB): This code opens a manpage file, and filters it from *
+	 * dangerous macros. The output is put into a temporary file, which is then *
+	 * used as the `name' filename argument of this(handlemanual) procedure.   *
+	 * There is a stored variable raw_tempfilename to allow unlinking this temp *
+	 * file after usage							    *
+	 ****************************************************************************/
+	/* if the pointer is non-null */
+	if (ignoredmacros)
+		/* if there are some macros */
+		if (*ignoredmacros && strlen(ignoredmacros))
+		{				/* that should be ignored   */
+			*location = '\0';
+			/* we need to know the path */
+			snprintf(cmd, 255, "man -W %s %s",
+					ManOptions,
+					name);
+			id = popen(cmd, "r");
+			if (!id)
+			{
+				printf(_("Error: Cannot call man command.\n"));
+				return 1;
+			}
+			fflush(id);
+			fgets(location, 255, id);
+			pclose(id);
+
+			if (*location == '\0')
+			{
+				printf(_("Error: No manual page found either.\n"));
+				if (use_apropos)
+				{
+					printf(_("Appropriate pages:\n"));
+					snprintf(cmd, 255, "apropos %s|cat %s", name, StderrRedirection);
+					system(cmd);
+				}
+				return 1;
+			}
+
+
+			ignored_items++;
+			prev = ignoredmacros;
+			/* counting items */
+			while ((end = strchr(prev, ':')))
+			{
+				ignored_items++;
+				prev = end + 1;
+			}
+
+			ignored_entries =(char **) (char*)xmalloc(ignored_items * sizeof(char **));
+			ignored_entries[0] = ignoredmacros;
+			prev = ignoredmacros;
+			i = 0;
+			/* creating pointers */
+			while ((end = strchr(prev, ':')))
+			{
+				*end = '\0';
+				prev = end + 1;
+				i++;
+				ignored_entries[i] = prev;
+			}
+
+			/* removing newline */
+			if ((prev = rindex(location, '\n')))
+				*prev = '\0';
+
+			/* checking if it's compressed */
+			prev = index(location, '\0');
+			if ((strlen(location)) > 3
+					&&((*(prev - 1) == 'Z' && *(prev - 2) == '.')
+						||(*(prev - 1) == 'z' && *(prev - 2) == 'g' && *(prev - 3) == '.')
+					   )
+			   )
+			{
+				if (verbose)
+					printf("%s %s\n", _("Calling gunzip for"), location);
+				snprintf(cmd, 255, "gunzip -c %s", location);
+				source = popen(cmd, "r");
+				zipped = 1;
+				if (!source)
+				{
+					printf(_("Couldn't call gunzip.\n"));
+					return 1;
+				}
+			}
+			else /* from cmd output  */
+				source = fopen(location, "r");
+			name = tempnam("/tmp", NULL);
+			raw_tempfilename = name;
+			id = fopen(name, "w");
+
+			/* we read until eof */
+			while (!feof(source))
+			{
+				if (fgets(line, 1024, source) == NULL)
+					line[0] = '\0';
+
+				/* macro starts with a dot*/
+				if (line[0] != '.' ||(strlen(line)) <(size_t) 2)
+				{
+					fprintf(id, "%s", line);
+					continue;
+				}
+				else
+					while (i >= 0)
+					{
+						macroline_size = strlen(ignored_entries[i]);
+						if (strlen(line + 1) < macroline_size)
+							macroline_size = strlen(line + 1);
+						if ((strncmp(ignored_entries[i], line + 1, macroline_size)) == 0
+								&&(*(line + 1 +(int) macroline_size) == ' '
+									|| *(line + 1 +(int) macroline_size) == '\n'
+									|| *(line + 1 +(int) macroline_size) == '\t'))
+						{
+							if (quote_ignored)
+							{
+								if ((prev = rindex(line, '\n')))
+									*prev = '\0';
+								sprintf(cmd, "\n.br\n.nf\n[ [pinfo] - %s: %.42s", _("IGNORING"), line);
+								if ((strlen(line)) >(size_t) 42)
+									strcat(cmd, "(...)]\n.fi\n");
+								else
+									strcat(cmd, " ]\n.fi\n");
+							}
+							else
+							{
+								sprintf(cmd, ".\\\" removed macro: %.42s", line);
+								if ((strlen(line)) >(size_t) 42)
+									strcat(cmd, "(...)");
+							}
+							strcpy(line, cmd);
+							break;
+						}
+						i--;
+					}
+
+				fprintf(id, "%s", line);
+				i = ignored_items - 1;
+			}			/* while (!feof(source)) */
+			if (zipped)
+				pclose(source);
+			else
+				fclose(source);
+			fclose(id);
+			free(ignored_entries);
+		}				/* if (ignored_macros... */
+	/****************************************************************************
+	 *                    Ignore macros part: END                               *
+	 ****************************************************************************/
+#endif
+	if (!plain_apropos)
+		snprintf(cmd, 255, "man %s %s %s > %s",
+				ManOptions,
+				name,
+				StderrRedirection,
+				tmpfilename1);
+	if ((plain_apropos) ||(system(cmd) != 0))
+	{
+		if (!plain_apropos)
+		{
+			unlink(tmpfilename1);
+			printf(_("Error: No manual page found\n"));
+		}
+		plain_apropos = 0;
+		if (use_apropos)
+		{
+			printf(_("Calling apropos \n"));
+			apropos_tempfilename = tempnam("/tmp", NULL);
+			snprintf(cmd, 255, "apropos %s > %s", name, apropos_tempfilename);
+			if (system(cmd) != 0)
+			{
+				printf(_("Nothing apropiate\n"));
+				unlink(apropos_tempfilename);
+				return 1;
+			}
+			id = fopen(apropos_tempfilename, "r");
+		}
+		else
+			return 1;
+	}
+	else
+		id = fopen(tmpfilename1, "r");
+	init_curses();
+
+
+	set_initial_history(name);
+	/* load manual to memory */
+	loadmanual(id);
+	fclose(id);
+	do
+	{
+		/* manualwork handles all actions when viewing man page */
+		return_value = manualwork();
+#ifdef getmaxyx
+		/* if ncurses, get maxx and maxy */
+		getmaxyx(stdscr, maxy, maxx);
+		if ((!getenv("MANWIDTH")) ||(manwidthChanged))
+		{
+			/* set MANWIDTH environment variable */
+			static char tmp[24];
+			snprintf(tmp, 24, "MANWIDTH=%d", maxx);
+			putenv(tmp);
+			manwidthChanged = 1;
+		}
+#endif
+		manual_aftersearch = 0;
+		/* -1 is quit key */
+		if (return_value != -1)
+		{
+			if (tmpfilename2)
+			{
+				unlink(tmpfilename2);
+				xfree(tmpfilename2);
+			}
+			tmpfilename2 = tempnam("/tmp", NULL);
+			/*
+			 * key_back is not pressed; and return_value is an offset to
+			 * manuallinks
+			 */
+			if (return_value != -2)
+			{
+				construct_manualname(manualname, return_value);
+				snprintf(cmd, 255, "man %s %s %s %s > %s",
+						ManOptions,
+						manuallinks[return_value].section,
+						manualname,
+						StderrRedirection,
+						tmpfilename2);
+			}
+			else /* key_back was pressed */
+			{
+				manualhistorylength--;
+				if (manualhistorylength == 0 && apropos_tempfilename)
+				{
+					id = fopen(apropos_tempfilename, "r");
+					loadmanual(id);
+					fclose(id);
+					continue;
+				}
+				if (manualhistory[manualhistorylength].sect[0] == 0)
+					snprintf(cmd, 255, "man %s %s %s > %s",
+							ManOptions,
+							manualhistory[manualhistorylength].name,
+							StderrRedirection,
+							tmpfilename2);
+				else
+					snprintf(cmd, 255, "man %s %s %s %s > %s",
+							ManOptions,
+							manualhistory[manualhistorylength].sect,
+							manualhistory[manualhistorylength].name,
+							StderrRedirection,
+							tmpfilename2);
+				/*
+				 * flag to make sure, that
+				 * manualwork will refresh the variables manualpos and selected
+				 * when going back to this page
+				 */
+				historical = 1;
+			}
+			system(cmd);
+			stat(tmpfilename2, &statbuf);
+			if (statbuf.st_size > 0)
+			{
+				snprintf(cmd, 255, "mv %s %s", tmpfilename2, tmpfilename1);
+				/* create tmp file containing man page */
+				system(cmd);
+				/* open man page */
+				id = fopen(tmpfilename1, "r");
+				if (id != NULL)
+				{
+					/* now we create history entry for new page */
+					if (!historical)
+					{
+						manualhistorylength++;
+						manualhistory = (manhistory*)xrealloc(manualhistory,(manualhistorylength + 2) * sizeof(manhistory));
+						/*
+						 * we can write so since this code applies
+						 * only when it's not a history call
+						 */
+						strcpy(manualhistory[manualhistorylength].name,
+								manualname);
+						strcpy(manualhistory[manualhistorylength].sect,
+								manuallinks[return_value].section);
+					}
+					/* loading manual page and its defaults... */
+					loadmanual(id);
+					fclose(id);
+					/* continuing with creation of history */
+					if (!historical)
+					{
+						manualhistory[manualhistorylength].pos = manualpos;
+						manualhistory[manualhistorylength].selected = selected;
+					}
+					else
+						historical = 0;
+				}
+				else
+					return_value = -1;
+			}
+		}
+	}
+	while (return_value != -1);
+	if (apropos_tempfilename)
+		unlink(apropos_tempfilename);
+	/* we were using temporary */
+	if (raw_tempfilename)
+		unlink(raw_tempfilename);
+	/* raw-manpage for scaning */
+	return 0;
+}
+
+void
+/* loads manual from given filedescriptor */
+loadmanual(FILE * id)
+{
+	char prevlinechar = 0;
+	/* tmp variable, set after reading first nonempty line of input */
+	int cutheader = 0;
+	int carryflag = 0;
+	manualpos = 0;
+	manual_free_buffers();
+	manual = (char**)xmalloc(sizeof(char *));
+	manuallinks = (manuallink*)xmalloc(sizeof(manuallinks));
+	manual[ManualLines] = (char*)xmalloc(1024);
+
+	/* we read until eof */
+	while (!feof(id))
+	{
+		char *tmp;
+		/*
+		 * it happens sometimes, that the last line is weird
+		 * and causes sigsegvs by not entering anything to buffer, what
+		 * confuses strlen
+		 */
+		if (fgets(manual[ManualLines], 1024, id) == NULL)
+			manual[ManualLines][0] = 0;
+
+		if (cutheader)
+		{
+			if (strcmp(manual[cutheader], manual[ManualLines]) == 0)
+			{
+				manual[ManualLines][0] = '\n';
+				manual[ManualLines][1] = 0;
+			}
+		}
+		if (FilterB7)
+		{
+			char *filter_pos = index(manual[ManualLines], 0xb7);
+			if (filter_pos)
+				*filter_pos = 'o';
+		}
+		if (CutManHeaders)
+			if (!cutheader)
+			{
+				if (strlen(manual[ManualLines]) > 1)
+				{
+					cutheader = ManualLines;
+				}
+			}
+		if ((CutEmptyManLines) &&((manual[ManualLines][0]) == '\n') &&
+				(prevlinechar == '\n'))
+			;			/* do nothing :)) */
+		else
+		{
+			int manlinelen = strlen(manual[ManualLines]);
+			manual[ManualLines] = (char*)xrealloc(manual[ManualLines],
+					manlinelen + 10);
+
+			/* temporary variable for determining hypertextuality of fields */
+			tmp = (char*)xmalloc(manlinelen + 10);
+
+			strcpy(tmp, manual[ManualLines]);
+
+			/* remove formatting chars */
+			strip_manual(tmp);
+			man_initializelinks(tmp, carryflag);
+			carryflag = 0;
+			if (manlinelen > 1)
+				if (ishyphen(manual[ManualLines][manlinelen - 2]))
+					carryflag = 1;
+			/* free temporary buffer */
+			xfree(tmp);
+			prevlinechar = manual[ManualLines][0];
+			/* increase the number of man lines */
+			ManualLines++;
+			/*
+			 * and realloc manual to add an empty space for
+			 * next entry of manual line
+			 */
+			manual = (char**)xrealloc(manual,(ManualLines + 5) * sizeof(char *));
+			manual[ManualLines] = (char*)xmalloc(1024);
+		}
+	}
+
+}
+
+int
+compare_manuallink(const void *a, const void *b)
+{
+	return ((manuallink *) a)->col -((manuallink *) b)->col;
+}
+
+void
+sort_manuallinks_from_current_line(long startlink, long endlink)
+{
+	qsort(manuallinks + startlink, endlink - startlink, sizeof(manuallink), compare_manuallink);
+}
+
+
+/* initializes hyperlinks in manual */
+void
+man_initializelinks(char *tmp, int carry)
+{
+	/* set tmpcnt to the trailing zero of tmp */
+	int tmpcnt = strlen(tmp) + 1;
+	char *link = tmp;
+	char *urlstart, *urlend;
+	long initialManualLinks = ManualLinks;
+	int i, b;
+	/******************************************************************************
+	 * handle url refrences                                                       *
+	 *****************************************************************************/
+	urlend = tmp;
+	while ((urlstart = strstr(urlend, "http://")) != NULL)
+	{
+		/* always successfull */
+		urlend = findurlend(urlstart);
+		manuallinks = (manuallink*)xrealloc(manuallinks, sizeof(manuallink) *(ManualLinks + 3));
+		manuallinks[ManualLinks].line = ManualLines;
+		manuallinks[ManualLinks].col = urlstart - tmp;
+		strcpy(manuallinks[ManualLinks].section, "HTTPSECTION");
+		manuallinks[ManualLinks].section_mark = HTTPSECTION;
+		manuallinks[ManualLinks].name = (char*)xmalloc(urlend - urlstart + 10);
+		strncpy(manuallinks[ManualLinks].name, urlstart, urlend - urlstart);
+		manuallinks[ManualLinks].name[urlend - urlstart] = 0;
+		if (ishyphen(manuallinks[ManualLinks].name[urlend - urlstart - 1]))
+			manuallinks[ManualLinks].carry = 1;
+		else
+			manuallinks[ManualLinks].carry = 0;
+		ManualLinks++;
+	}
+	urlend = tmp;
+	while ((urlstart = strstr(urlend, "ftp://")) != NULL)
+	{
+		/* always successfull */
+		urlend = findurlend(urlstart);
+		manuallinks = (manuallink*)xrealloc(manuallinks, sizeof(manuallink) *(ManualLinks + 3));
+		manuallinks[ManualLinks].line = ManualLines;
+		manuallinks[ManualLinks].col = urlstart - tmp;
+		strcpy(manuallinks[ManualLinks].section, "FTPSECTION");
+		manuallinks[ManualLinks].section_mark = FTPSECTION;
+		manuallinks[ManualLinks].name = (char*)xmalloc(urlend - urlstart + 10);
+		strncpy(manuallinks[ManualLinks].name, urlstart, urlend - urlstart);
+		manuallinks[ManualLinks].name[urlend - urlstart] = 0;
+		if (ishyphen(manuallinks[ManualLinks].name[urlend - urlstart - 1]))
+			manuallinks[ManualLinks].carry = 1;
+		else
+			manuallinks[ManualLinks].carry = 0;
+		ManualLinks++;
+	}
+	urlend = tmp;
+	while ((urlstart = findemailstart(urlend)) != NULL)
+	{
+		/* always successfull */
+		urlend = findurlend(urlstart);
+		manuallinks = (manuallink*)xrealloc(manuallinks, sizeof(manuallink) *(ManualLinks + 3));
+		manuallinks[ManualLinks].line = ManualLines;
+		manuallinks[ManualLinks].col = urlstart - tmp;
+		strcpy(manuallinks[ManualLinks].section, "MAILSECTION");
+		manuallinks[ManualLinks].section_mark = MAILSECTION;
+		manuallinks[ManualLinks].name = (char*)xmalloc(urlend - urlstart + 10);
+		strncpy(manuallinks[ManualLinks].name, urlstart, urlend - urlstart);
+		manuallinks[ManualLinks].name[urlend - urlstart] = 0;
+		if (ishyphen(manuallinks[ManualLinks].name[urlend - urlstart - 1]))
+			manuallinks[ManualLinks].carry = 1;
+		else
+			manuallinks[ManualLinks].carry = 0;
+
+		/* there should be a dot in e-mail domain */
+		if (strchr(manuallinks[ManualLinks].name, '.') != NULL)
+			ManualLinks++;
+	}
+	/******************************************************************************
+	 * handle normal manual refrences -- reference(section)                       *
+	 ******************************************************************************/
+	do
+	{
+		/* we look for '(', since manual link */
+		link = strchr(link, '(');
+		/* has form of  'blah(x)' */
+		if (link != NULL)
+		{
+			char *temp;
+			/* look for the closing bracket */
+			if ((temp = strchr(link, ')')))
+			{
+				char *p_t1, *p_t;
+				p_t = p_t1 = (char*)xmalloc((strlen(link) + 10) * sizeof(char));
+				for (++link; link != temp; *p_t++ = *link++);
+				*p_t = '\0';
+				link -=(strlen(p_t1) + sizeof(char));
+
+				if ((!strchr(p_t1, '(')) &&(!is_in_manlinks(manlinks, p_t1)))
+				{
+					char tempchar;
+					int breakpos;
+					i = link - tmp - 1;
+					if (i < 0)
+						i++;
+					for (; i > 0; --i)
+					{
+						if (!isspace(tmp[i]))
+							/* ignore spaces between linkname and '(x)' */
+							break;
+					}
+					/* we'll put zero on the last non-textual character of link */
+					breakpos = i + 1;
+					/* but remember the cleared char for the future */
+					tempchar = tmp[breakpos];
+					tmp[breakpos] = 0;
+					/*
+					 * scan to the first space sign or to 0 -- that means go to
+					 * the beginning of the scanned token
+					 */
+					for (i = breakpos; i > 0; --i)
+					{
+						if (isspace(tmp[i]))
+						{
+							i++;
+							break;
+						}
+					}
+					/* now we have needed string in i..breakpos. We need now to
+					 * realloc the
+					 * manuallinks table to make free space for new entry
+					 */
+
+					/* a small check */
+					if (!((use_apropos) &&(manualhistorylength == 0)))
+					{
+						/*
+						 * In English: if the name of the link is the name of
+						 * the current page and the section of the link is the
+						 * current section or if we don't know the current
+						 * section, then...
+						 */
+						if ((!strcasecmp(&tmp[i], manualhistory[manualhistorylength].name))
+								&&((!strcasecmp(p_t1, manualhistory[manualhistorylength].sect))
+									||(manualhistory[manualhistorylength].sect[0] == 0)
+									||(!strcmp(manualhistory[manualhistorylength].sect, " "))))
+
+							break;
+					}
+					manuallinks = (manuallink*)xrealloc(manuallinks, sizeof(manuallink) *(ManualLinks + 3));
+					manuallinks[ManualLinks].line = ManualLines;
+					manuallinks[ManualLinks].col = i;
+					if (LongManualLinks)
+					{
+						for (b = 1; link[b] != ')'; b++)
+							manuallinks[ManualLinks].section[b - 1] = tolower(link[b]);
+						manuallinks[ManualLinks].section[b - 1] = 0;
+					}
+					else
+					{
+						manuallinks[ManualLinks].section[0] = link[1];
+						manuallinks[ManualLinks].section[1] = 0;
+					}
+					manuallinks[ManualLinks].section_mark = 0;
+					manuallinks[ManualLinks].name = (char*)xmalloc((breakpos - i) + 10);
+					strcpy(manuallinks[ManualLinks].name, tmp + i);
+					tmp[breakpos] = tempchar;
+
+					/* check whether this is a carry'ed entry(i.e. in the
+					 * previous line there was `-' at end, and this is the
+					 * first word of this line */
+					for (b = i - 1; b >= 0; b--)
+					{
+						if (b > 0)
+							if (!isspace(tmp[b]))
+								break;
+					}
+					if (b >= 0)
+						manuallinks[ManualLinks].carry = 0;
+					else
+						manuallinks[ManualLinks].carry = carry;
+					/* increase the number of entries */
+					ManualLinks++;
+				}		/*... if (in man links) */
+				xfree((void *) p_t1);
+			}
+		}
+		if (link)
+			link++;
+		if (link >(tmp + tmpcnt))
+		{
+			break;
+		}
+	}
+	/* do this line until strchr() won't find a '(' in string */
+	while (link != NULL);
+	if (initialManualLinks != ManualLinks)
+		sort_manuallinks_from_current_line(initialManualLinks, ManualLinks);
+}
+
+/* viewer function. Handles keyboard actions--main event loop */
+int
+manualwork()
+{
+	/* for user's shell commands */
+	FILE *pipe;
+	/* a temporary buffer */
+	char *token;
+	/* again the same */
+	char *tmp;
+	/* key, which contains the value entered by user */
+	int key = 0;
+	/* tmp values */
+	int i, selectedchanged;
+	int statusline = FREE;
+#ifdef getmaxyx
+	/* if ncurses, get maxx and maxy */
+	getmaxyx(stdscr, maxy, maxx);
+	if ((!getenv("MANWIDTH")) ||(manwidthChanged))
+	{
+		/* set MANWIDTH environment variable */
+		static char tmp[24];
+		snprintf(tmp, 24, "MANWIDTH=%d", maxx);
+		putenv(tmp);
+		manwidthChanged = 1;
+	}
+#else
+	maxx = 80;
+	/* otherwise hardcode 80x25... */
+	maxy = 25;
+#endif /* getmaxyx */
+
+	/* get manualpos from history.  it is set in handlemanual() */
+	manualpos = manualhistory[manualhistorylength].pos;
+	/* if there was a valid selected entry, apply it */
+	if (manualhistory[manualhistorylength].selected != -1)
+		selected = manualhistory[manualhistorylength].selected;
+	else /* otherwise scan for selected on currently viewed page */
+		rescan_selected();
+
+	/* clean screen */
+	erase();
+
+	/* user events loop. finish when key_quit */
+	while (1)
+	{
+		/* make getch not wait for user */
+		nodelay(stdscr, TRUE);
+		/* action -- return ERR */
+		key = pinfo_getch();
+		/* if there was nothing in buffer */
+		if (key == ERR)
+		{
+			/* then show screen */
+			if (statusline == FREE)
+				showmanualscreen();
+			wrefresh(stdscr);
+			waitforgetch();
+			key = pinfo_getch();
+		}
+		nodelay(stdscr, FALSE);
+		statusline = FREE;
+		if (winchanged)
+		{
+			handlewinch();
+			winchanged = 0;
+			key = pinfo_getch();
+		}
+		/************************ keyboard handling **********************************/
+		if (key != 0)
+		{
+			if ((key == keys.print_1) ||
+					(key == keys.print_2))
+			{
+				if (yesno(_("Are you sure to print?"), 0))
+					printmanual(manual, ManualLines);
+			}
+			/*====================================================*/
+			if ((key == keys.goto_1) ||
+					(key == keys.goto_2))
+			{
+				manuallinks = (manuallink*)xrealloc(manuallinks,(ManualLinks + 1) *(sizeof(manuallink) + 3));
+
+				/* get user's value */
+				attrset(bottomline);
+				move(maxy - 1, 0);
+				echo();
+				curs_set(1);
+				manuallinks[ManualLinks].name = getstring(_("Enter manual name: "));
+				curs_set(0);
+				noecho();
+				move(maxy - 1, 0);
+#ifdef HAVE_BKGDSET
+				bkgdset(' ' | bottomline);
+				clrtoeol();
+				bkgdset(0);
+#else
+				myclrtoeol();
+#endif
+				attrset(normal);
+
+				manuallinks[ManualLinks].carry = 0;
+				manuallinks[ManualLinks].section_mark = 0;
+				strcpy(manuallinks[ManualLinks].section, " ");
+				manuallinks[ManualLinks].line = -1;
+				manuallinks[ManualLinks].col = -1;
+				ManualLinks++;
+				return ManualLinks - 1;
+			}
+			/*====================================================*/
+			if ((key == keys.goline_1) ||
+					(key == keys.goline_2))
+			{
+				long newpos;
+				/* get user's value */
+				attrset(bottomline);
+				move(maxy - 1, 0);
+				echo();
+				curs_set(1);
+				token = getstring(_("Enter line: "));
+				curs_set(0);
+				noecho();
+				move(maxy - 1, 0);
+#ifdef HAVE_BKGDSET
+				bkgdset(' ' | bottomline);
+				clrtoeol();
+				bkgdset(0);
+#else
+				myclrtoeol();
+#endif
+				attrset(normal);
+				/* convert string to long.  careful with nondigit strings.  */
+				if (token)
+				{
+					int digit_val = 1;
+					for (i = 0; token[i] != 0; i++)
+					{
+						if (!isdigit(token[i]))
+							digit_val = 0;
+					}
+					/* move cursor position */
+					if (digit_val)
+					{
+						newpos = atol(token);
+						newpos -=(maxy - 1);
+						if ((newpos >= 0) &&(newpos < ManualLines -(maxy - 2)))
+							manualpos = newpos;
+						else if (newpos > 0)
+							manualpos = ManualLines -(maxy - 2);
+						else
+							manualpos = 0;
+					}
+					xfree(token);
+					token = 0;
+				}
+			}
+			/*=====================================================*/
+			if ((key == keys.shellfeed_1) ||
+					(key == keys.shellfeed_2))
+			{
+				/* get command name */
+				curs_set(1);
+				attrset(bottomline);
+				move(maxy - 1, 0);
+				echo();
+				/* get users cmd */
+				token = getstring(_("Enter command: "));
+				noecho();
+				move(maxy - 1, 0);
+#ifdef HAVE_BKGDSET
+				bkgdset(' ' | bottomline);
+				clrtoeol();
+				bkgdset(0);
+#else
+				myclrtoeol();
+#endif
+				attrset(normal);
+
+				myendwin();
+				system("clear");
+				/* open pipe */
+				pipe = popen(token, "w");
+				if (pipe != NULL)
+				{
+					/* and flush the msg to stdin */
+					for (i = 0; i < ManualLines; i++)
+						fprintf(pipe, "%s", manual[i]);
+					pclose(pipe);
+				}
+				getchar();
+				doupdate();
+				curs_set(0);
+			}
+			/*=====================================================*/
+			if ((key == keys.refresh_1) ||
+					(key == keys.refresh_2))
+			{
+				myendwin();
+				doupdate();
+				refresh();
+				curs_set(0);
+			}
+			/*=====================================================*/
+			/* search in current node */
+			if ((key == keys.search_1) ||
+					(key == keys.search_2))
+			{
+				int success = 0;
+				/* procedure of getting regexp string */
+				move(maxy - 1, 0);
+				attrset(bottomline);
+				echo();
+				curs_set(1);
+				/*
+				 * searchagain handler. see keys.totalsearch at mainfunction.c
+				 * for comments
+				 */
+				if (!searchagain.search)
+				{
+					token = getstring(_("Enter regexp: "));
+					strcpy(searchagain.lastsearch, token);
+					searchagain.type = key;
+				}
+				else
+				{
+					token = (char*)xmalloc(strlen(searchagain.lastsearch) + 1);
+					strcpy(token, searchagain.lastsearch);
+					searchagain.search = 0;
+				}		/* end of searchagain handler */
+				if (strlen(token) == 0)
+				{
+					xfree(token);
+					goto skip_search;
+				}
+				curs_set(0);
+				noecho();
+				move(maxy - 1, 0);
+#ifdef HAVE_BKGDSET
+				bkgdset(' ' | bottomline);
+				clrtoeol();
+				bkgdset(0);
+#else
+				myclrtoeol();
+#endif
+				attrset(normal);
+				/* compile regexp expression */
+				if (pinfo_re_comp(token) != 0)
+				{
+					/* print error message */
+					attrset(bottomline);
+					mymvhline(maxy - 1, 0, ' ', maxx);
+					move(maxy - 1, 0);
+					printw(_("Invalid regular expression;"));
+					printw(" ");
+					printw(_("Press any key to continue..."));
+					getch();
+					goto skip_search;
+				}
+				/* and search for it in all subsequential lines */
+				for (i = manualpos + 1; i < ManualLines - 1; i++)
+				{
+					tmp = (char*)xmalloc(strlen(manual[i]) + strlen(manual[i + 1]) + 10);
+					/*
+					 * glue two following lines together, to find expres- sions
+					 * split up into two lines
+					 */
+					strcpy(tmp, manual[i]);
+					strcat(tmp, manual[i + 1]);
+					strip_manual(tmp);
+
+					/* execute search */
+					if (pinfo_re_exec(tmp))
+					{		/* if found, enter here... */
+						success = 1;
+						strcpy(tmp, manual[i + 1]);
+						strip_manual(tmp);
+						/*
+						 * if it was found in the second line of the glued
+						 * expression.
+						 */
+						if (pinfo_re_exec(tmp))
+							manualpos = i + 1;
+						else
+							manualpos = i;
+						xfree(tmp);
+						break;
+					}
+					xfree(tmp);
+				}
+				xfree(token);
+				rescan_selected();
+				if (!success)
+				{
+					attrset(bottomline);
+					mvaddstr(maxy - 1, 0, _("Search string not found..."));
+					statusline = LOCKED;
+				}
+
+				manual_aftersearch = 1;
+			}
+			/*=====================================================*/
+			/* search again */
+			/* see mainfunction.c for comments */
+			if ((key == keys.search_again_1) ||
+					(key == keys.search_again_2))
+			{
+				if (searchagain.type != 0)
+				{
+					searchagain.search = 1;
+					ungetch(searchagain.type);
+				}
+			}
+skip_search:
+			/*=====================================================*/
+			if ((key == keys.twoup_1) ||
+					(key == keys.twoup_2))
+			{
+				ungetch(keys.up_1);
+				ungetch(keys.up_1);
+			}
+			/*=====================================================*/
+			if ((key == keys.up_1) ||
+					(key == keys.up_2))
+			{
+				selectedchanged = 0;
+				/* if there are links at all */
+				if (selected != -1)
+				{
+					/* if one is selected */
+					if (selected > 0)
+						/*
+						 * scan for a next visible one, which is above the
+						 * current.
+						 */
+						for (i = selected - 1; i >= 0; i--)
+						{
+							if ((manuallinks[i].line >= manualpos) &&
+									(manuallinks[i].line < manualpos +(maxy - 1)))
+							{
+								selected = i;
+								selectedchanged = 1;
+								break;
+							}
+						}
+				}
+				/* if new link not found */
+				if (!selectedchanged)
+				{
+					/* move one position up */
+					if (manualpos >= 1)
+						manualpos--;
+					/* and scan for selected again :) */
+					for (i = 0; i < ManualLinks; i++)
+					{
+						if (manuallinks[i].line == manualpos)
+						{
+							selected = i;
+							break;
+						}
+					}
+				}
+			}
+			/*=====================================================*/
+			if ((key == keys.end_1) ||
+					(key == keys.end_2))
+			{
+				manualpos = ManualLines -(maxy - 1);
+				if (manualpos < 0)
+					manualpos = 0;
+				selected = ManualLinks - 1;
+			}
+			/*=====================================================*/
+			if ((key == keys.nextnode_1) ||
+					(key == keys.nextnode_2))
+			{
+				for (i = manualpos + 1; i < ManualLines; i++)
+				{
+					if (manual[i][1] == 8)
+					{
+						manualpos = i;
+						break;
+					}
+				}
+			}
+			/*=====================================================*/
+			if ((key == keys.prevnode_1) ||
+					(key == keys.prevnode_2))
+			{
+				for (i = manualpos - 1; i > 0; i--)
+				{
+					if (manual[i][1] == 8)
+					{
+						manualpos = i;
+						break;
+					}
+				}
+			}
+			/*=====================================================*/
+			if ((key == keys.pgdn_1) ||
+					(key == keys.pgdn_2))
+			{
+				if (manualpos +(maxy - 2) < ManualLines -(maxy - 1))
+				{
+					manualpos +=(maxy - 2);
+					rescan_selected();
+				}
+				else if (ManualLines -(maxy - 1) >= 1)
+				{
+					manualpos = ManualLines -(maxy - 1);
+					selected = ManualLinks - 1;
+				}
+				else
+				{
+					manualpos = 0;
+					selected = ManualLinks - 1;
+				}
+			}
+			/*=====================================================*/
+			if ((key == keys.home_1) || (key == keys.home_2))
+			{
+				manualpos = 0;
+				rescan_selected();
+			}
+			/*=====================================================*/
+			if ((key == keys.pgup_1) | (key == keys.pgup_2))
+			{
+				if (manualpos >(maxy - 1))
+					manualpos -=(maxy - 1);
+				else
+					manualpos = 0;
+				rescan_selected();
+			}
+			/*=====================================================*/
+			/* top+bottom line \|/ */
+			/* see keys.up for comments */
+			if ((key == keys.twodown_1) || (key == keys.twodown_2))
+			{
+				ungetch(keys.down_1);
+				ungetch(keys.down_1);
+			}
+			/*=====================================================*/
+			/* top+bottom line \|/ */
+			/* see keys.up for comments */
+			if ((key == keys.down_1) || (key == keys.down_2))
+			{
+				selectedchanged = 0;
+				if (selected < ManualLinks)
+					for (i = selected + 1; i < ManualLinks; i++)
+					{
+						if ((manuallinks[i].line >= manualpos) &&
+								(manuallinks[i].line < manualpos +(maxy - 2)))
+						{
+							selected = i;
+							selectedchanged = 1;
+							break;
+						}
+					}
+				if (!selectedchanged)
+				{
+					if (manualpos < ManualLines -(maxy - 1))
+						manualpos++;
+					if (selected < ManualLinks)
+						for (i = selected + 1; i < ManualLinks; i++)
+						{
+							if ((manuallinks[i].line >= manualpos) &&
+									(manuallinks[i].line < manualpos +(maxy - 2)))
+							{
+								selected = i;
+								selectedchanged = 1;
+								break;
+							}
+						}
+				}
+			}
+			/*=====================================================*/
+			if ((key == keys.back_1) ||
+					(key == keys.back_2))
+			{
+				if (manualhistorylength)
+					return -2;
+			}
+			/*=====================================================*/
+			if ((key == keys.followlink_1) ||
+					(key == keys.followlink_2))
+			{
+				manualhistory[manualhistorylength].pos = manualpos;
+				manualhistory[manualhistorylength].selected = selected;
+				if (selected >= 0)
+					if ((manuallinks[selected].line >= manualpos) &&
+							(manuallinks[selected].line < manualpos +(maxy - 1)))
+					{
+						if (!strncmp(manuallinks[selected].section, "HTTPSECTION", 11))
+						{
+							int buflen;
+							char *tempbuf = (char*)xmalloc(1024);
+							strcpy(tempbuf, httpviewer);
+							strcat(tempbuf, " ");
+							buflen = strlen(tempbuf);
+							construct_manualname(tempbuf + buflen, selected);
+							myendwin();
+							system(tempbuf);
+							doupdate();
+							xfree(tempbuf);
+						}
+						else if (!strncmp(manuallinks[selected].section, "FTPSECTION", 10))
+						{
+							int buflen;
+							char *tempbuf = (char*)xmalloc(1024);
+							strcpy(tempbuf, ftpviewer);
+							strcat(tempbuf, " ");
+							buflen = strlen(tempbuf);
+							construct_manualname(tempbuf + buflen, selected);
+							myendwin();
+							system(tempbuf);
+							doupdate();
+							xfree(tempbuf);
+						}
+						else if (!strncmp(manuallinks[selected].section, "MAILSECTION", 11))
+						{
+							int buflen;
+							char *tempbuf = (char*)xmalloc(1024);
+							strcpy(tempbuf, maileditor);
+							strcat(tempbuf, " ");
+							buflen = strlen(tempbuf);
+							construct_manualname(tempbuf + buflen, selected);
+							myendwin();
+							system(tempbuf);
+							doupdate();
+							xfree(tempbuf);
+						}
+						else
+						{
+							return selected;
+						}
+					}
+			}
+			/*=====================================================*/
+			if ((key==keys.left_1)||(key==keys.left_2))
+				if (manualcol>0) manualcol--;
+			if ((key==keys.right_1)||(key==keys.right_2))
+				manualcol++;
+			/*=====================================================*/
+			/********* end of keyboard handling *********************/
+			/********* mouse handler ********************************/
+#ifdef NCURSES_MOUSE_VERSION
+			if (key == KEY_MOUSE)
+			{
+				MEVENT mouse;
+				int done = 0;
+				getmouse(&mouse);
+				if (mouse.bstate == BUTTON1_CLICKED)
+				{
+					if ((mouse.y > 0) &&(mouse.y < maxy - 1))
+					{
+						for (i = selected; i > 0; i--)
+						{
+							if (manuallinks[i].line == mouse.y + manualpos - 1)
+							{
+								if (manuallinks[i].col <= mouse.x - 1)
+								{
+									if (manuallinks[i].col + strlen(manuallinks[i].name) >= mouse.x - 1)
+									{
+										selected = i;
+										done = 1;
+										break;
+									}
+								}
+							}
+						}
+						if (!done)
+							for (i = selected; i < ManualLinks; i++)
+							{
+								if (manuallinks[i].line == mouse.y + manualpos - 1)
+								{
+									if (manuallinks[i].col <= mouse.x - 1)
+									{
+										if (manuallinks[i].col + strlen(manuallinks[i].name) >= mouse.x - 1)
+										{
+											selected = i;
+											done = 1;
+											break;
+										}
+									}
+								}
+							}
+					}		/* end: mouse not on top/bottom line */
+					if (mouse.y == 0)
+						ungetch(keys.up_1);
+					if (mouse.y == maxy - 1)
+						ungetch(keys.down_1);
+				}		/* end: button_clicked */
+				if (mouse.bstate == BUTTON1_DOUBLE_CLICKED)
+				{
+					if ((mouse.y > 0) &&(mouse.y < maxy - 1))
+					{
+						for (i = selected; i > 0; i--)
+						{
+							if (manuallinks[i].line == mouse.y + manualpos - 1)
+							{
+								if (manuallinks[i].col <= mouse.x - 1)
+								{
+									if (manuallinks[i].col + strlen(manuallinks[i].name) >= mouse.x - 1)
+									{
+										selected = i;
+										done = 1;
+										break;
+									}
+								}
+							}
+						}
+						if (!done)
+							for (i = selected; i < ManualLinks; i++)
+							{
+								if (manuallinks[i].line == mouse.y + manualpos - 1)
+								{
+									if (manuallinks[i].col <= mouse.x - 1)
+									{
+										if (manuallinks[i].col + strlen(manuallinks[i].name) >= mouse.x - 1)
+										{
+											selected = i;
+											done = 1;
+											break;
+										}
+									}
+								}
+							}
+						if (done)
+							ungetch(keys.followlink_1);
+					}		/* end: mouse not at top/bottom line */
+					if (mouse.y == 0)
+						ungetch(keys.pgup_1);
+					if (mouse.y == maxy - 1)
+						ungetch(keys.pgdn_1);
+				}		/* end: button doubleclicked */
+			}
+#endif
+			/*****************************************************************************/
+		}
+		if ((key == keys.quit_2) ||(key == keys.quit_1))
+		{
+			if (!ConfirmQuit)
+				break;
+			else
+			{
+				if (yesno(_("Are you sure to quit?"), QuitConfirmDefault))
+					break;
+			}
+		}
+	}
+	closeprogram();
+	return -1;
+}
+
+void
+/* scan for some hyperlink, available on current screen */
+rescan_selected()
+{
+	int i;
+	for (i = 0; i < ManualLinks; i++)
+	{
+		if ((manuallinks[i].line >= manualpos) &&
+				(manuallinks[i].line < manualpos +(maxy - 1)))
+		{
+			selected = i;
+			break;
+		}
+	}
+}
+
+/*
+ * calculate from which to start displaying of manual line *man. Skip `mancol'
+ * columns. But remember, that *man contains also nonprinteble characters for
+ * boldface etc.
+ */
+char *getmancolumn(char *man, int mancol)
+{
+	if (mancol==0) return man;
+	while (mancol>0)
+	{ if (*(man+1) == 8) man+=3; else man++; mancol--; }
+	return man;
+}
+
+/* show the currently visible part of manpage */
+void
+showmanualscreen()
+{
+	int i;
+#ifdef getmaxyx
+	/* refresh maxy, maxx values */
+	getmaxyx(stdscr, maxy, maxx);
+#endif
+	attrset(normal);
+	/* print all visible text lines */
+	for (i = manualpos;(i < manualpos +(maxy - 2)) &&(i < ManualLines); i++)
+	{
+		int len = strlen(manual[i]);
+		if (len)
+			manual[i][len - 1] = ' ';
+		/* if we have something to display */
+		if (len>manualcol)
+			mvaddstr_manual((i - manualpos) + 1, 0, getmancolumn(manual[i],manualcol));
+		else	/* otherwise, just clear the line to eol */
+		{
+			move((i - manualpos) + 1, 0);
+			bkgdset(' ' | normal);
+			clrtoeol();
+		}
+		if (len)
+			manual[i][len - 1] = '\n';
+	}
+#ifdef HAVE_BKGDSET
+	bkgdset(' ' | normal);
+#endif
+	/* and clear to bottom */
+	clrtobot();
+#ifdef HAVE_BKGDSET
+	bkgdset(0);
+#endif
+	attrset(normal);
+	/* add highlights */
+	add_highlights();
+	/* draw bottomline with user informations */
+	attrset(bottomline);
+	mymvhline(0, 0, ' ', maxx);
+	mymvhline(maxy - 1, 0, ' ', maxx);
+	move(maxy - 1, 0);
+	if (((manualpos + maxy) < ManualLines) &&(ManualLines > maxy - 2))
+		printw(_("Viewing line %d/%d, %d%%"),(manualpos - 1 + maxy), ManualLines,((manualpos - 1 + maxy) * 100) / ManualLines);
+	else
+		printw(_("Viewing line %d/%d, 100%%"), ManualLines, ManualLines);
+	move(maxy - 1, 0);
+	attrset(normal);
+}
+
+void
+/* print a manual line */
+mvaddstr_manual(int y, int x, char *str)
+{
+	int i, j, len = strlen(str);
+	static char strippedline[1024];
+	if ((h_regexp_num) ||(manual_aftersearch))
+	{
+		memcpy(strippedline, str, len + 1);
+		strip_manual(strippedline);
+	}
+	move(y, x);
+	for (i = 0; i < len; i++)
+	{
+		if ((i > 0) &&(i < len - 1))
+		{
+			/* handle bold highlight */
+			if ((str[i] == 8) &&(str[i - 1] == '_'))
+			{
+				attrset(manualbold);
+				addch(str[i] & 0xff);
+				addch(str[i + 1] & 0xff);
+				attrset(normal);
+				i++;
+				goto label_skip_other;
+			}
+			/*
+			 * if it wasn't bold, check italic, before default, unhighlighted
+			 * line will be painted.  We can do it only if i<len-3.
+			 */
+			else if (i < len - 3)
+				goto label_check_italic;
+			else /* unhighlighted */
+			{
+				addch(str[i] & 0xff);
+				goto label_skip_other;
+			}
+		}
+		/* italic highlight */
+		if (i < len - 3)
+		{
+label_check_italic:
+			if ((str[i + 1] == 8) &&(str[i + 2] == str[i]))
+			{
+				attrset(manualitalic);
+				addch(str[i] & 0xff);
+				i += 2;
+				attrset(normal);
+			}
+			else
+			{
+				addch(str[i] & 0xff);
+			}
+		}
+label_skip_other:;
+	}
+#ifdef HAVE_BKGDSET
+	bkgdset(' ' | normal);
+	clrtoeol();
+	bkgdset(0);
+#else
+	myclrtoeol();
+#endif
+	attrset(normal);
+#ifndef ___DONT_USE_REGEXP_SEARCH___
+	if ((h_regexp_num) ||(manual_aftersearch))
+	{
+		regmatch_t pmatch[1];
+		int maxregexp = manual_aftersearch ? h_regexp_num + 1 : h_regexp_num;
+
+		/* if it is after search, then we have user defined regexps+
+		   a searched regexp to highlight */
+		for (j = 0; j < maxregexp; j++)
+		{
+			char *tmpstr = strippedline;
+			while (!regexec(&h_regexp[j], tmpstr, 1, pmatch, 0))
+			{
+				int n = pmatch[0].rm_eo - pmatch[0].rm_so, k;
+				int rx = pmatch[0].rm_so + tmpstr - strippedline;
+				int curY, curX;
+				char tmpchr;
+				getyx(stdscr, curY, curX);
+				tmpchr = strippedline[rx + n];
+				strippedline[rx + n] = 0;
+				attrset(searchhighlight);
+				mvaddstr(y, rx, strippedline + rx);
+				attrset(normal);
+				strippedline[rx + n] = tmpchr;
+				tmpstr = tmpstr + pmatch[0].rm_eo;
+				move(curY, curX);
+			}
+		}
+	}
+#endif
+}
+
+/* add hyperobject highlights */
+void
+add_highlights()
+{
+	int i;
+	/* scan through the visible objects */
+	for (i = 0; i < ManualLinks; i++)
+	{
+		/* if the object is on the current screen */
+		if ((manuallinks[i].line >= manualpos) &&
+				(manuallinks[i].line < manualpos +(maxy - 2)))
+		{
+			/* if it's a simple man link */
+			if (manuallinks[i].section_mark < HTTPSECTION)
+			{
+				if (i == selected)
+					attrset(noteselected);
+				else
+					attrset(note);
+
+				/* if it's a link split into two lines */
+				if (manuallinks[i].carry == 1)
+				{
+					int x, y, ltline = manuallinks[i].line - 1;
+					/* find the line, where starts the split link */
+					char *tmpstr = strdup(manual[ltline]);
+					int ltlinelen;
+					char *newlinemark;
+					/* remove boldfaces&italics */
+					strip_manual(tmpstr);
+					/* calculate the length of this line */
+					ltlinelen = strlen(tmpstr);
+					/* set this var to the last character of this line(to an '\n')*/
+					newlinemark = tmpstr + ltlinelen - 1;
+					getyx(stdscr, y, x);
+					if (y > 2)
+					{
+#define TestCh tmpstr[ltlinelen]
+						/* skip \n, -, and the at least one char... */
+						if (ltlinelen > 2)
+							ltlinelen -= 3;
+
+						/*
+						 * positon ltlinelen to the beginning of the link to be
+						 * highlighted
+						 */
+						while ((isalpha(TestCh)) ||(TestCh == '.') ||(TestCh == '_'))
+							ltlinelen--;
+
+						*newlinemark = 0;
+						/* OK, link horizontally fits into screen */
+						if (ltlinelen>manualcol)
+							mvaddstr(manuallinks[i].line - manualpos + 1 - 1,
+									ltlinelen-manualcol, &tmpstr[ltlinelen]);
+						/*
+						 * we cut here a part of the link, and draw only what's
+						 * visible on screen
+						 */
+						else if (ltlinelen+strlen(&tmpstr[ltlinelen])>manualcol)
+							mvaddstr(manuallinks[i].line - manualpos + 1 - 1,
+									ltlinelen-manualcol, &tmpstr[manualcol]);
+
+						*newlinemark = '\n';
+#undef TestCh
+					}
+					xfree(tmpstr);
+					move(y, x);
+				}
+			}
+			else
+			{
+				if (i == selected)
+					attrset(urlselected);
+				else
+					attrset(url);
+				if (manuallinks[i].carry == 1)
+				{
+					int x, y, ltline = manuallinks[i].line + 1;
+					/*
+					 * the split part to find is lying down
+					 * to the line defined in manlinks(line+1)
+					 */
+					char *tmpstr = strdup(manual[ltline]);
+					char *wsk = tmpstr, *wskend;
+					strip_manual(tmpstr);
+					/* skip spaces */
+					while (isspace(*wsk))
+						wsk++;
+					/* find the end of url */
+					wskend = findurlend(wsk);
+					/* add end of string, and print */
+					*wskend = 0;
+					if (wsk-tmpstr<manualcol)
+						mvaddstr(manuallinks[i].line - manualpos + 2, wsk - tmpstr - manualcol, wsk);
+					else if (wskend-tmpstr<manualcol)
+						mvaddstr(manuallinks[i].line - manualpos + 2, 0, wsk+manualcol);
+				}
+			}
+			if (manuallinks[i].col>manualcol)
+				mvaddstr(1 + manuallinks[i].line - manualpos,
+						manuallinks[i].col - manualcol, manuallinks[i].name);
+			else if (manuallinks[i].col+strlen(manuallinks[i].name)>manualcol)
+				mvaddstr(1 + manuallinks[i].line - manualpos, 0,
+						manuallinks[i].name+(manualcol-manuallinks[i].col));
+			attrset(normal);
+		}
+	}
+}
+
+/* all variables passed here must have, say 10 bytes of overrun buffer */
+void
+strip_manual(char *buf)
+{
+	int i, tmpcnt = 0;
+	/* in general, tmp buffer will hold a line stripped from highlight marks */
+	for (i = 0; buf[i] != 0; i++)
+	{
+		/* so we strip the line from "'_',0x8" -- bold marks */
+		if ((buf[i] == '_') &&(buf[i + 1] == 8))
+		{
+			buf[tmpcnt++] = buf[i + 2];
+			i += 2;
+		}
+		/* and 0x8 -- italic marks */
+		else if ((buf[i + 1] == 8) &&(buf[i + 2] == buf[i]))
+		{
+			buf[tmpcnt++] = buf[i];
+			i += 2;
+		}
+		else /* else we don't do anything */
+			buf[tmpcnt++] = buf[i];
+	}
+	buf[tmpcnt] = 0;
+}
+
+/*
+ * checks if a construction, which looks like hyperlink, belongs to the allowed
+ * manual sections.
+ */
+int
+is_in_manlinks(char *in, char *find)
+{
+	char *copy, *token;
+	const char delimiters[] = ":";
+
+	copy = strdup(in);
+	if ((strcmp(find,(token = strtok(copy, delimiters))) != 0))
+	{
+		while ((token = strtok(NULL, delimiters)))
+		{
+#ifdef HAVE_STRCASECMP
+			if (!strcasecmp(token, find))
+#else
+				if (!strcmp(token, find))
+#endif
+				{
+					xfree((void *) copy);
+					return 0;
+				}
+		}
+		xfree((void *) copy);
+		return 1;
+	}
+	else
+	{
+		xfree((void *) copy);
+		return 0;
+	}
+}
+
+void
+printmanual(char **Message, long Lines)
+{
+	/* printer fd */
+	FILE *prnFD;
+	int i;
+
+	prnFD = popen(printutility, "w");
+
+	/* scan through all lines */
+	for (i = 0; i < Lines; i++)
+	{
+		fprintf(prnFD, "\r%s", Message[i]);
+	}
+	pclose(prnFD);
+}
+
+int
+ishyphen(unsigned char ch)
+{
+	if ((ch == '-') ||(ch == SOFT_HYPHEN))
+		return 1;
+	return 0;
+}

Deleted: pinfo/branches/cxx/src/menu_and_note_utils.c

Copied: pinfo/branches/cxx/src/menu_and_note_utils.cxx (from rev 30, pinfo/branches/cxx/src/menu_and_note_utils.c)

Deleted: pinfo/branches/cxx/src/parse_config.c

Copied: pinfo/branches/cxx/src/parse_config.cxx (from rev 30, pinfo/branches/cxx/src/parse_config.c)
===================================================================
--- pinfo/branches/cxx/src/parse_config.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/parse_config.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,989 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+
+#include "common_includes.h"
+
+RCSID("$Id$")
+
+#include <ctype.h>
+
+#define COLOR_DEFAULT -1	/* mutt uses this was for transparency */
+
+regex_t *h_regexp = 0;	/* regexps to highlight */
+int h_regexp_num = 0;	/* number of those regexps */
+
+extern int use_apropos;
+extern int CutManHeaders;
+extern int DontHandleWithoutTagTable;
+extern int use_manual;
+extern int use_raw_filename;
+extern int quote_ignored;
+extern char *httpviewer;
+extern char *ftpviewer;
+extern char *maileditor;
+extern char *manlinks;
+extern char *ignoredmacros;
+
+struct keybindings keys =
+{
+	's',		'S',		/* regexp search */
+	'/',		'/',		/* regexp search, this page */
+	'g',		'G',		/* goto node */
+	'p',		'P',		/* previous node */
+	'n',		'N',		/* next node */
+	'u',		'U',		/* up node */
+	KEY_UP,		'k',		/* up one line */
+#ifdef HAVE_KEY_END
+	KEY_END
+#else	/* HAVE_KEY_END */
+	'E'
+#endif	/* HAVE_KEY_END */
+		,'e',			/* end */
+	KEY_NPAGE,	' ',		/* down one page */
+	KEY_HOME,	'H',		/* home */
+	KEY_PPAGE,	'-',		/* up one page */
+	KEY_DOWN,	'j',		/* down one line */
+	't',		'T',		/* top */
+	KEY_LEFT,	'h',		/* back */
+	KEY_RIGHT,	'\n',		/* follow link */
+	'Q',		'q',		/* quit */
+	12,			'~',		/* refresh screen -- 12 is C-L */
+	'!',		'!',		/* shell feed */
+	'D',		'd',		/* goto dir page */
+	0,			' ',		/* pgdn_auto */
+	0,			'-',		/* pgup_auto */
+	'f',		0,			/* search again */
+	'l',		0,			/* go to line */
+	KEY_IC,		0,			/* two lines up */
+	KEY_DC,		1,			/* two lines down */
+	']',		0, 			/* print */
+	'4',		0,			/* scroll left */
+	'6',		0			/* scroll right */
+};
+
+#ifndef NO_COLOR_CURSES
+struct colours cols =
+{
+	COLOR_WHITE,	COLOR_BLACK,	NO_BOLD,	NO_BLINK,	/* normal */
+	COLOR_GREEN,	COLOR_WHITE,	BOLD,		NO_BLINK,	/* selected menu */
+	COLOR_GREEN,	COLOR_BLACK,	BOLD,		NO_BLINK,	/* menu */
+	COLOR_BLUE,		COLOR_WHITE,	BOLD,		NO_BLINK,	/* selected note */
+	COLOR_BLUE,		COLOR_BLACK,	BOLD,		NO_BLINK,	/* note */
+	COLOR_GREEN,	COLOR_BLUE,		BOLD,		NO_BLINK,	/* top line */
+	COLOR_GREEN,	COLOR_BLUE,		BOLD,		NO_BLINK,	/* bottom line */
+	COLOR_YELLOW,	COLOR_BLACK,	BOLD,		NO_BLINK,	/* manual bold */
+	COLOR_WHITE,	COLOR_BLACK,	BOLD,		NO_BLINK,	/* manual italic */
+	COLOR_MAGENTA,	COLOR_BLACK,	BOLD,		NO_BLINK,	/* url */
+	COLOR_MAGENTA,	COLOR_GREEN,	NO_BOLD,	NO_BLINK,	/* url selected */
+	COLOR_WHITE,	COLOR_BLACK,	BOLD,		NO_BLINK,	/* info highlight(quoted text) */
+	COLOR_YELLOW,	COLOR_BLACK,	BOLD,		NO_BLINK	/* search highlight */
+};
+#endif /* NO_COLOR_CURSES */
+
+int
+parse_config(void)
+{
+	char config_file_name[256], *home = 0;
+	char line[256];
+	FILE *f;
+	int line_number = 0;
+	if (rcfile != NULL)
+	{
+		f = fopen(rcfile, "r");
+		if (f == NULL)
+		{
+			fprintf(stderr, _("Can't open config file!\n"));
+			exit(1);
+		}
+	}
+	else
+	{
+		if (rcfile == NULL)
+			if (getenv("HOME"))
+				home = strdup(getenv("HOME"));
+			else
+				home = 0;
+		if (home)
+		{
+			strcpy(config_file_name, home);
+			strcat(config_file_name, "/.pinforc");
+			if (!(f = fopen(config_file_name, "r")))
+			{
+				strcpy(config_file_name, CONFIGDIR);
+				if (!(f = fopen(config_file_name, "r")))
+				{
+					free(home);	/* home is nonzero; see if (home) above */
+					return 0;	/* no config file available */
+				}
+			}
+		}
+		else
+		{
+			strcpy(config_file_name, CONFIGDIR);
+			if (!(f = fopen(config_file_name, "r")))
+			{
+				/* free(home);    home is unallocated; see if (home) above */
+				return 0;
+			}
+		}
+	}
+	while (!feof(f))
+	{
+		if (!(fgets(line, 255, f)))
+		{
+			fclose(f);
+			if (home)
+				free(home);
+			return 0;
+		}
+		if (parse_line(line))
+		{
+			line_number++;
+			fclose(f);
+			fprintf(stderr, _("Parse error in config file on line %d\n"), line_number);
+			exit(1);
+		}
+		else
+			line_number++;
+	}
+
+	fclose(f);
+	if (home)
+		free(home);
+	return 0;
+}
+
+int
+parse_line(char *line)
+{
+	char *temp;
+	int *fore = NULL;
+	int *key = NULL;
+#ifdef HAS_CURSES
+	int *back = NULL, *bold = NULL, *blink = NULL, *p = NULL;
+	int i;
+#endif /* HAS_CURSES */
+
+	if (line[0] == '#')
+		return 0;
+
+	if (!(temp = skip_whitespace(strtok(line, "="))))
+		return 1;
+
+	temp = str_toupper(temp);
+
+	if (strlen(temp) < 1)
+		return 0;
+
+	if (!strncmp(temp, "KEY", 3))
+	{
+		fore = NULL;
+		if (!strncmp(temp + 4, "TOTALSEARCH_1", 13))
+			key = &keys.totalsearch_1;
+		else if (!strncmp(temp + 4, "PGDN_AUTO_1", 11))
+			key = &keys.pgdn_auto_1;
+		else if (!strncmp(temp + 4, "PGDN_AUTO_2", 11))
+			key = &keys.pgdn_auto_2;
+		else if (!strncmp(temp + 4, "PGUP_AUTO_1", 11))
+			key = &keys.pgup_auto_1;
+		else if (!strncmp(temp + 4, "PGUP_AUTO_2", 11))
+			key = &keys.pgup_auto_2;
+		else if (!strncmp(temp + 4, "TOTALSEARCH_2", 13))
+			key = &keys.totalsearch_2;
+		else if (!strncmp(temp + 4, "SEARCH_AGAIN_1", 14))
+			key = &keys.search_again_1;
+		else if (!strncmp(temp + 4, "SEARCH_AGAIN_2", 14))
+			key = &keys.search_again_2;
+		else if (!strncmp(temp + 4, "SEARCH_1", 8))
+			key = &keys.search_1;
+		else if (!strncmp(temp + 4, "SEARCH_2", 8))
+			key = &keys.search_2;
+		else if (!strncmp(temp + 4, "GOTO_1", 6))
+			key = &keys.goto_1;
+		else if (!strncmp(temp + 4, "GOTO_2", 6))
+			key = &keys.goto_2;
+		else if (!strncmp(temp + 4, "PREVNODE_1", 10))
+			key = &keys.prevnode_1;
+		else if (!strncmp(temp + 4, "PREVNODE_2", 10))
+			key = &keys.prevnode_2;
+		else if (!strncmp(temp + 4, "NEXTNODE_1", 10))
+			key = &keys.nextnode_1;
+		else if (!strncmp(temp + 4, "NEXTNODE_2", 10))
+			key = &keys.nextnode_2;
+		else if (!strncmp(temp + 4, "UPNODE_1", 8))
+			key = &keys.upnode_1;
+		else if (!strncmp(temp + 4, "UPNODE_2", 8))
+			key = &keys.upnode_2;
+		else if (!strncmp(temp + 4, "UP_1", 4))
+			key = &keys.up_1;
+		else if (!strncmp(temp + 4, "UP_2", 4))
+			key = &keys.up_2;
+		else if (!strncmp(temp + 4, "TWOUP_1", 7))
+			key = &keys.twoup_1;
+		else if (!strncmp(temp + 4, "TWOUP_2", 7))
+			key = &keys.twoup_2;
+		else if (!strncmp(temp + 4, "END_1", 5))
+			key = &keys.end_1;
+		else if (!strncmp(temp + 4, "END_2", 5))
+			key = &keys.end_2;
+		else if (!strncmp(temp + 4, "PGDN_1", 6))
+			key = &keys.pgdn_1;
+		else if (!strncmp(temp + 4, "PGDN_2", 6))
+			key = &keys.pgdn_2;
+		else if (!strncmp(temp + 4, "HOME_1", 6))
+			key = &keys.home_1;
+		else if (!strncmp(temp + 4, "HOME_2", 6))
+			key = &keys.home_2;
+		else if (!strncmp(temp + 4, "PGUP_1", 6))
+			key = &keys.pgup_1;
+		else if (!strncmp(temp + 4, "PGUP_2", 6))
+			key = &keys.pgup_2;
+		else if (!strncmp(temp + 4, "DOWN_1", 6))
+			key = &keys.down_1;
+		else if (!strncmp(temp + 4, "DOWN_2", 6))
+			key = &keys.down_2;
+		else if (!strncmp(temp + 4, "TWODOWN_1", 9))
+			key = &keys.twodown_1;
+		else if (!strncmp(temp + 4, "TWODOWN_2", 9))
+			key = &keys.twodown_2;
+		else if (!strncmp(temp + 4, "TOP_1", 5))
+			key = &keys.top_1;
+		else if (!strncmp(temp + 4, "TOP_2", 5))
+			key = &keys.top_2;
+		else if (!strncmp(temp + 4, "BACK_1", 6))
+			key = &keys.back_1;
+		else if (!strncmp(temp + 4, "BACK_2", 6))
+			key = &keys.back_2;
+		else if (!strncmp(temp + 4, "FOLLOWLINK_1", 12))
+			key = &keys.followlink_1;
+		else if (!strncmp(temp + 4, "FOLLOWLINK_2", 12))
+			key = &keys.followlink_2;
+		else if (!strncmp(temp + 4, "REFRESH_1", 9))
+			key = &keys.refresh_1;
+		else if (!strncmp(temp + 4, "REFRESH_2", 9))
+			key = &keys.refresh_2;
+		else if (!strncmp(temp + 4, "SHELLFEED_1", 11))
+			key = &keys.shellfeed_1;
+		else if (!strncmp(temp + 4, "SHELLFEED_2", 11))
+			key = &keys.shellfeed_2;
+		else if (!strncmp(temp + 4, "QUIT_1", 6))
+			key = &keys.quit_1;
+		else if (!strncmp(temp + 4, "QUIT_2", 6))
+			key = &keys.quit_2;
+		else if (!strncmp(temp + 4, "DIRPAGE_1", 9))
+			key = &keys.dirpage_1;
+		else if (!strncmp(temp + 4, "DIRPAGE_2", 9))
+			key = &keys.dirpage_2;
+		else if (!strncmp(temp + 4, "GOLINE_1", 8))
+			key = &keys.goline_1;
+		else if (!strncmp(temp + 4, "GOLINE_2", 8))
+			key = &keys.goline_2;
+		else if (!strncmp(temp + 4, "PRINT_1", 7))
+			key = &keys.print_1;
+		else if (!strncmp(temp + 4, "PRINT_2", 7))
+			key = &keys.print_2;
+		else if (!strncmp(temp + 4, "LEFT_1", 6))
+			key = &keys.left_1;
+		else if (!strncmp(temp + 4, "LEFT_2", 6))
+			key = &keys.left_2;
+		else if (!strncmp(temp + 4, "RIGHT_1", 7))
+			key = &keys.right_1;
+		else if (!strncmp(temp + 4, "RIGHT_2", 7))
+			key = &keys.right_2;
+		else
+			return 1;
+	}
+#ifndef NO_COLOR_CURSES
+	else if (!strncmp(temp, "COL", 3))
+	{
+		key = NULL;
+		if (!strncmp(temp + 4, "NORMAL", 6))
+		{
+			fore = &cols.normal_fore;
+			back = &cols.normal_back;
+			bold = &cols.normal_bold;
+			blink = &cols.normal_blink;
+		}
+		else if (!strncmp(temp + 4, "MENUSELECTED", 12))
+		{
+			fore = &cols.menuselected_fore;
+			back = &cols.menuselected_back;
+			bold = &cols.menuselected_bold;
+			blink = &cols.menuselected_blink;
+		}
+		else if (!strncmp(temp + 4, "MENU", 4))
+		{
+			fore = &cols.menu_fore;
+			back = &cols.menu_back;
+			bold = &cols.menu_bold;
+			blink = &cols.menu_blink;
+		}
+		else if (!strncmp(temp + 4, "NOTESELECTED", 12))
+		{
+			fore = &cols.noteselected_fore;
+			back = &cols.noteselected_back;
+			bold = &cols.noteselected_bold;
+			blink = &cols.noteselected_blink;
+		}
+		else if (!strncmp(temp + 4, "NOTE", 4))
+		{
+			fore = &cols.note_fore;
+			back = &cols.note_back;
+			bold = &cols.note_bold;
+			blink = &cols.note_blink;
+		}
+		else if (!strncmp(temp + 4, "TOPLINE", 7))
+		{
+			fore = &cols.topline_fore;
+			back = &cols.topline_back;
+			bold = &cols.topline_bold;
+			blink = &cols.topline_blink;
+		}
+		else if (!strncmp(temp + 4, "BOTTOMLINE", 10))
+		{
+			fore = &cols.bottomline_fore;
+			back = &cols.bottomline_back;
+			bold = &cols.bottomline_bold;
+			blink = &cols.bottomline_blink;
+		}
+		else if (!strncmp(temp + 4, "MANUALBOLD", 10))
+		{
+			fore = &cols.manualbold_fore;
+			back = &cols.manualbold_back;
+			bold = &cols.manualbold_bold;
+			blink = &cols.manualbold_blink;
+		}
+		else if (!strncmp(temp + 4, "MANUALITALIC", 12))
+		{
+			fore = &cols.manualitalic_fore;
+			back = &cols.manualitalic_back;
+			bold = &cols.manualitalic_bold;
+			blink = &cols.manualitalic_blink;
+		}
+		else if (!strncmp(temp + 4, "URLSELECTED", 11))
+		{
+			fore = &cols.urlselected_fore;
+			back = &cols.urlselected_back;
+			bold = &cols.urlselected_bold;
+			blink = &cols.urlselected_blink;
+		}
+		else if (!strncmp(temp + 4, "URL", 3))
+		{
+			fore = &cols.url_fore;
+			back = &cols.url_back;
+			bold = &cols.url_bold;
+			blink = &cols.url_blink;
+		}
+		else if (!strncmp(temp + 4, "INFOHIGHLIGHT", 13))
+		{
+			fore = &cols.infohighlight_fore;
+			back = &cols.infohighlight_back;
+			bold = &cols.infohighlight_bold;
+			blink = &cols.infohighlight_blink;
+		}
+		else if (!strncmp(temp + 4, "SEARCHHIGHLIGHT", 15))
+		{
+			fore = &cols.searchhighlight_fore;
+			back = &cols.searchhighlight_back;
+			bold = &cols.searchhighlight_bold;
+			blink = &cols.searchhighlight_blink;
+		}
+		else
+			return 1;
+	}
+#endif /* NO_COLOR_CURSES */
+	else if (!strncmp(temp, "MANUAL", 6))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				use_manual = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				use_manual = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "RAW-FILENAME", 12))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				use_raw_filename = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				use_raw_filename = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "APROPOS", 7))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				use_apropos = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				use_apropos = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "VERBOSE", 7))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				verbose = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				verbose = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "QUIT-CONFIRMATION", 17))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				ConfirmQuit = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				ConfirmQuit = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "QUIT-CONFIRM-DEFAULT", 20))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "YES", 3))
+				QuitConfirmDefault = 1;
+			else if (!strncmp(temp, "NO", 2))
+				QuitConfirmDefault = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "CUT-MAN-HEADERS", 15))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				CutManHeaders = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				CutManHeaders = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "CLEAR-SCREEN-AT-EXIT", 20))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				ClearScreenAtExit = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				ClearScreenAtExit = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "CALL-READLINE-HISTORY", 21))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				CallReadlineHistory = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				CallReadlineHistory = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "CUT-EMPTY-MAN-LINES", 19))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				CutEmptyManLines = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				CutEmptyManLines = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "DONT-HANDLE-WITHOUT-TAG-TABLE", 28))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				DontHandleWithoutTagTable = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				DontHandleWithoutTagTable = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "LONG-MANUAL-LINKS", 17))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				LongManualLinks = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				LongManualLinks = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "HTTPVIEWER", 10))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			httpviewer = strdup(temp);
+			remove_quotes(httpviewer);
+		}
+		else
+			return 1;
+	}
+	else if (!strncmp(temp, "FTPVIEWER", 10))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			ftpviewer = strdup(temp);
+			remove_quotes(ftpviewer);
+		}
+		else
+			return 1;
+	}
+	else if (!strncmp(temp, "MAILEDITOR", 10))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			maileditor = strdup(temp);
+			remove_quotes(maileditor);
+		}
+		else
+			return 1;
+	}
+	else if (!strncmp(temp, "PRINTUTILITY", 12))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			printutility = strdup(temp);
+			remove_quotes(printutility);
+		}
+		else
+			return 1;
+	}
+	else if (!strncmp(temp, "MAN-OPTIONS", 11))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			ManOptions = strdup(temp);
+			remove_quotes(ManOptions);
+		}
+		else
+			return 1;
+	}
+	else if (!strncmp(temp, "STDERR-REDIRECTION", 18))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			StderrRedirection = strdup(temp);
+			remove_quotes(StderrRedirection);
+		}
+		else
+			return 1;
+	}
+	else if (!strncmp(temp, "FILTER-0XB7", 11))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				FilterB7 = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				FilterB7 = 0;
+			else
+				return 1;
+		}
+	}
+	else if (!strncmp(temp, "MANLINKS", 8))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			manlinks = strdup(temp);
+			remove_quotes(manlinks);
+		}
+		else
+			return 1;
+	}
+	else if (!strncmp(temp, "INFOPATH", 8))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			configuredinfopath = strdup(temp);
+			remove_quotes(configuredinfopath);
+		}
+		else
+			return 1;
+	}
+#ifndef ___DONT_USE_REGEXP_SEARCH___
+	else if (!strncmp(temp, "HIGHLIGHTREGEXP", 15))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			char *tmp = strdup(temp);
+			remove_quotes(tmp);
+			if (!h_regexp_num)
+				h_regexp = (regex_t*)malloc(sizeof(regex_t));
+			else
+				h_regexp = (regex_t*)realloc(h_regexp, sizeof(regex_t) *(h_regexp_num + 1));
+			regcomp(&h_regexp[h_regexp_num], tmp, 0);
+			free(tmp);
+			h_regexp_num++;
+		}
+		else
+			return 1;
+	}
+#endif
+	else if (!strncmp(temp, "SAFE-USER", 9))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			char *tmp = strdup(temp);
+			remove_quotes(tmp);
+			safe_user = tmp;
+		}
+		else
+			return 1;
+	}
+	else if (!strncmp(temp, "SAFE-GROUP", 10))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			char *tmp = strdup(temp);
+			remove_quotes(tmp);
+			safe_group = tmp;
+		}
+		else
+			return 1;
+	}
+	else if (!strncmp(temp, "QUOTE-IGNORED-MACROS", 20))
+	{
+		temp = strtok(NULL, "=");
+		if (temp)
+		{
+			if (!(temp = str_toupper(skip_whitespace(temp))))
+				return 1;
+			if (!strncmp(temp, "TRUE", 4))
+				quote_ignored = 1;
+			else if (!strncmp(temp, "FALSE", 5))
+				quote_ignored = 0;
+			else
+				return 1;
+		}
+	}
+
+	else if (!strncmp(temp, "IGNORE-MACROS", 8))
+	{
+		temp = strtok(NULL, "\n");
+		if (temp)
+		{
+			ignoredmacros = strdup(temp);
+			remove_quotes(ignoredmacros);
+			if (ignoredmacros[0] == '\t' || ignoredmacros[0] == ' '
+					|| !strncasecmp(ignoredmacros, "FALSE", 5))
+				ignoredmacros[0] = '\0';
+		}
+		else
+			return 1;
+	}
+	else
+		return 1;
+#ifndef NO_COLOR_CURSES
+	if (fore)
+	{
+		for (i = 0; i < 4; i++)
+		{
+			if (i == 0)
+				p = fore;
+			else if (i == 1)
+				p = back;
+			else if (i == 2)
+				p = bold;
+			else
+				p = blink;
+
+			if (!(temp = skip_whitespace(strtok(NULL, ","))))
+				return 1;
+
+			temp = str_toupper(temp);
+
+			if (!(strncmp(temp, "COLOR_BLACK", 11)))
+				*p = COLOR_BLACK;
+			else if (!(strncmp(temp, "COLOR_RED", 9)))
+				*p = COLOR_RED;
+			else if (!(strncmp(temp, "COLOR_GREEN", 11)))
+				*p = COLOR_GREEN;
+			else if (!(strncmp(temp, "COLOR_BLUE", 10)))
+				*p = COLOR_BLUE;
+			else if (!(strncmp(temp, "COLOR_WHITE", 11)))
+				*p = COLOR_WHITE;
+			else if (!(strncmp(temp, "COLOR_YELLOW", 12)))
+				*p = COLOR_YELLOW;
+			else if (!(strncmp(temp, "COLOR_CYAN", 10)))
+				*p = COLOR_CYAN;
+			else if (!(strncmp(temp, "COLOR_MAGENTA", 13)))
+				*p = COLOR_MAGENTA;
+			else if (!(strncmp(temp, "COLOR_DEFAULT", 13)))
+				*p = COLOR_DEFAULT;
+			else if (!(strncmp(temp, "BOLD", 4)))
+				*p = BOLD;
+			else if (!(strncmp(temp, "NO_BOLD", 7)))
+				*p = 0;
+			else if (!(strncmp(temp, "BLINK", 4)))
+				*p = BOLD;
+			else if (!(strncmp(temp, "NO_BLINK", 7)))
+				*p = 0;
+			else
+				return 1;
+		}
+	}
+	else
+#endif /* NO_COLOR_CURSES */
+		if (key)
+		{
+			if (!(temp = skip_whitespace(strtok(NULL, "="))))
+				return 0;
+			if (!(strncmp(temp, "KEY_", 4)) ||
+					!(strncmp(temp, "key_", 4)))
+			{
+				str_toupper(temp);
+				/* what other keys should be interesting?  all in curs_getch? */
+				if (!(strncmp(temp + 4, "BREAK", 5)))
+					*key = KEY_BREAK;
+				else if (!(strncmp(temp + 4, "DOWN", 4)))
+					*key = KEY_DOWN;
+				else if (!(strncmp(temp + 4, "UP", 2)))
+					*key = KEY_UP;
+				else if (!(strncmp(temp + 4, "LEFT", 4)))
+					*key = KEY_LEFT;
+				else if (!(strncmp(temp + 4, "RIGHT", 5)))
+					*key = KEY_RIGHT;
+				else if (!(strncmp(temp + 4, "IC", 2)))
+					*key = KEY_IC;
+				else if (!(strncmp(temp + 4, "DC", 2)))
+					*key = KEY_DC;
+				else if (!(strncmp(temp + 4, "HOME", 4)))
+					*key = KEY_HOME;
+				else if (!(strncmp(temp + 4, "BACKSPACE", 9)))
+					*key = KEY_BACKSPACE;
+				else if (!(strncmp(temp + 4, "NPAGE", 5)))
+					*key = KEY_NPAGE;
+				else if (!(strncmp(temp + 4, "PPAGE", 5)))
+					*key = KEY_PPAGE;
+				else if (!(strncmp(temp + 4, "F(1)", 4)))
+					*key = KEY_F(1);
+				else if (!(strncmp(temp + 4, "F(2)", 4)))
+					*key = KEY_F(2);
+				else if (!(strncmp(temp + 4, "F(3)", 4)))
+					*key = KEY_F(3);
+				else if (!(strncmp(temp + 4, "F(4)", 4)))
+					*key = KEY_F(4);
+				else if (!(strncmp(temp + 4, "F(5)", 4)))
+					*key = KEY_F(5);
+				else if (!(strncmp(temp + 4, "F(6)", 4)))
+					*key = KEY_F(6);
+				else if (!(strncmp(temp + 4, "F(7)", 4)))
+					*key = KEY_F(7);
+				else if (!(strncmp(temp + 4, "F(8)", 4)))
+					*key = KEY_F(8);
+				else if (!(strncmp(temp + 4, "(F9)", 4)))
+					*key = KEY_F(9);
+				else if (!(strncmp(temp + 4, "(F10)", 5)))
+					*key = KEY_F(10);
+				else if (!(strncmp(temp + 4, "F(11)", 5)))
+					*key = KEY_F(11);
+				else if (!(strncmp(temp + 4, "F(12)", 5)))
+					*key = KEY_F(12);
+#ifdef USE_NCURSES
+				else if (!(strncmp(temp + 4, "END", 3)))
+					*key = KEY_END;
+#endif
+				else if (!(strncmp(temp + 4, "CTRL", 4)))
+				{
+					if (!(temp = skip_whitespace(temp + 8)))
+						return 1;
+					if (temp[0] == '(')
+					{
+						if (temp[1] == '\'')
+							*key = KEY_CTRL(temp[2]);
+						else if (isdigit(temp[1]))
+						{
+							char *tail = temp +(strlen(temp));
+							*key = KEY_CTRL((int) strtol(temp + 1, &tail, 10));
+						}
+						else
+							return 1;
+					}
+					else
+						return 1;
+				}
+				else if (!(strncmp(temp + 4, "ALT", 3)))
+				{
+					if (!(temp = skip_whitespace(temp + 7)))
+						return 1;
+					if (temp[0] == '(')
+					{
+						if (temp[1] == '\'')
+							*key = KEY_ALT(tolower(temp[2]));
+						else if (isdigit(temp[1]))
+						{
+							char *tail = temp +(strlen(temp));
+							*key = KEY_ALT((int) strtol(temp + 1, &tail, 10));
+						}
+						else
+							return 1;
+					}
+					else
+						return 1;
+				}
+				else
+					return 1;
+			}
+			else if (!(strncmp(temp, "\'", 1)))
+			{
+				if (!(strncmp(temp + 1, "\\", 1)))
+				{
+					if (temp[2] == 'n')
+						*key = '\n';
+					else if (temp[2] == '\\')
+						*key = '\\';
+					else if (temp[2] == 't')
+						*key = '\t';
+					else if (temp[2] == '\'')
+						*key = '\'';
+					else
+						*key = temp[2];
+				}
+				else
+				{
+					*key = temp[1];
+				}
+			}
+			else if (isdigit(temp[0]))
+			{
+				char *tail = temp +(strlen(temp));
+				*key =(int) strtol(temp, &tail, 10);
+			}
+		}
+
+	return 0;
+}
+
+char *
+str_toupper(char *str)
+{
+	int i;
+
+	for (i = 0; i < strlen(str); ++i)
+		if (islower(str[i]))
+			str[i] = toupper(str[i]);
+
+	return str;
+}
+
+char *
+skip_whitespace(char *str)
+{
+	int i = 0;
+
+	if (!str)
+		return NULL;
+
+	while (str[i] == ' ' || str[i] == '\t' || str[i] == '\n')
+		i++;
+
+	return str + i;
+}
+
+char *
+remove_quotes(char *str)
+{
+	int i = 0;
+
+	for (i = 0; i < strlen(str); i++)
+		if (str[i] == '\"')
+			str[i] = ' ';
+
+	return str;
+}

Modified: pinfo/branches/cxx/src/parse_config.h
===================================================================
--- pinfo/branches/cxx/src/parse_config.h	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/parse_config.h	2005-08-22 21:00:13 UTC (rev 31)
@@ -85,7 +85,7 @@
 colours;
 #endif /* NO_COLOR_CURSES */
 
-int use_manual;
+extern int use_manual;
 
 int parse_config (void);
 int parse_line (char *line);

Deleted: pinfo/branches/cxx/src/pinfo.c

Copied: pinfo/branches/cxx/src/pinfo.cxx (from rev 30, pinfo/branches/cxx/src/pinfo.c)
===================================================================
--- pinfo/branches/cxx/src/pinfo.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/pinfo.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,617 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+
+#include "common_includes.h"
+#include "utils.h"
+
+RCSID(PKG_VER "$Id$")
+
+#ifdef HAVE_GETOPT_LONG
+ #include <getopt.h>
+#endif
+
+char *version = VERSION;
+int DontHandleWithoutTagTable = 0;
+
+/* currently viewed filename */
+char *curfile = 0;
+
+/* node specified by --node option */
+char *pinfo_start_node = 0;
+
+/* strip `.info' suffix from  "file" */
+void strip_file_from_info_suffix(char *file);
+/* add `.info' suffix to "file" */
+char *addinfosuffix(char *file);
+
+/* protect against bad, bad macros */
+void checksu();
+
+int
+main(int argc, char *argv[])
+{
+	int filenotfound = 0;
+	char filename[256];
+	WorkRVal work_return_value =
+	{0, 0};
+	int i, userdefinedrc = 0;
+	int command_line_option;
+	FILE *id = NULL;
+	/* line count in message */
+	long lines = 0;
+	/* this will hold node's text */
+	char **message = 0;
+	/* this will hold the node's header */
+	char *type = 0;
+	int tag_table_pos = 1;
+	char *tmp;
+#ifdef HAVE_GETOPT_LONG
+	static struct option long_options[] =
+	{
+		{"help", 0, 0, 'h'},
+		{"version", 0, 0, 'v'},
+		{"manual", 0, 0, 'm'},
+		{"file", 0, 0, 'f'},
+		{"raw-filename", 0, 0, 'r'},
+		{"apropos", 0, 0, 'a'},
+		{"plain-apropos", 0, 0, 'p'},
+		{"cut-man-headers", 0, 0, 'c'},
+		{"squeeze-manlines", 0, 0, 's'},
+		{"dont-handle-without-tag-table", 0, 0, 'd'},
+		{"force-manual-tag-table", 0, 0, 't'},
+		{"node", 1, 0, 'n'},
+		{"long-manual-links", 0, 0, 'l'},
+		{"clear-at-exit", 0, 0, 'x'},
+		/* no one-letter shortcut :( */
+		{"rcfile", 1, 0, 1},
+		{0, 0, 0, 0}};
+#endif
+		/* take care of SIGSEGV, SIGTERM, SIGINT */
+		signal_handler();
+		searchagain.type = 0;
+		searchagain.search = 0;
+		initlocale();
+		inithistory();
+		for (i = 1; i < argc; i++)
+			if (strncmp(argv[i], "--rcfile", 8) == 0)
+				userdefinedrc = 1;
+		/* read config information */
+		if (!userdefinedrc)
+			parse_config();
+		if (verbose)
+			printf("Przemek's Info Viewer v%s\n", version);
+		/* if no arguments were given */
+		if (argc == 1)
+		{
+			id = openinfo("dir", 0);
+			curfile = (char*)xmalloc(150);
+			strcpy(curfile, "dir");
+			strcpy(filename, "dir");
+		}
+		if ((strlen(argv[0]) >= 3)||(use_manual))
+			/* handle any 'man' alias to 'pinfo' */
+			if ((strstr(argv[0], "man") != NULL)||(use_manual))
+			{
+				if (verbose)
+					printf(_("Looking for man page...\n"));
+				strcpy(filename, "");
+				/*
+				 * pass all arguments to the `man' command(manhandler calls
+				 * `man')
+				 */
+				for (i = 1; i < argc; i++)
+				{
+					strcat(filename, argv[i]);
+					strcat(filename, " ");
+				}
+				exit(handlemanual(filename));
+			}
+
+
+
+#ifdef HAVE_GETOPT_LONG
+
+		/******************************************************************************
+		 * Parse command line options(getopt)                                         *
+		 ******************************************************************************/
+
+		do
+		{
+			command_line_option = getopt_long(argc, argv,
+					"hvmfrapcsdtnlx", long_options, NULL);
+			switch(command_line_option)
+			{
+				case 'x':
+					ClearScreenAtExit = 1;
+					break;
+				case 'l':
+					LongManualLinks = 1;
+					break;
+				case 'n':
+					if (!optarg)
+					{
+						printf(_("--node option used without argument\n"));
+						exit(1);
+					}
+					pinfo_start_node = (char*)malloc(strlen(optarg) + 1);
+					strcpy(pinfo_start_node, optarg);
+					break;
+				/* rcfile */
+				case 1:
+					if (!optarg)
+					{
+						printf(_("--rcfile option used without argument\n"));
+						exit(1);
+					}
+					rcfile = strdup(optarg);
+					/* parse user-defined config file */
+					parse_config();
+					break;
+				case 't':
+					ForceManualTagTable = 1;
+					break;
+				case 'h':
+					printf(_("Usage:\n" \
+								"%s [options] [info|manual]\n" \
+								"Options:\n" \
+								"-h, --help                            help\n" \
+								"-v, --version                         version\n" \
+								"-m, --manual                          use man page\n" \
+								"-r, --raw-filename                    use raw filename\n" \
+								"-f, --file                            synonym for -r\n" \
+								"-a, --apropos                         call apropos if nothing found\n" \
+								"-p, --plain-apropos                   call only apropos\n" \
+								"-c, --cut-man-headers                 cut out repeated man headers\n" \
+								"-l, --long-manual-links               use long link names in manuals\n" \
+								"-s, --squeeze-manlines                cut empty lines from manual pages\n" \
+								"-d, --dont-handle-without-tag-table   don't display texinfo pages without tag\n" \
+								"                                      tables\n" \
+								"-t, --force-manual-tag-table          force manual detection of tag table\n" \
+								"-x, --clear-at-exit                   clear screen at exit\n" \
+								"    --node=nodename, --node nodename  jump directly to the node nodename\n" \
+								"    --rcfile=file, --rcfile file      use alternate rcfile\n"),
+							argv[0]);
+					exit(0);
+				case 'v':
+					exit(0);
+				case 'm':
+					checksu();
+					if (verbose)
+						printf(_("Looking for man page...\n"));
+					strcpy(filename, "");
+					for (i = optind; i < argc; i++)
+					{
+						strcat(filename, argv[i]);
+						strcat(filename, " ");
+					}
+					exit(handlemanual(filename));
+				case 'f':
+				case 'r':
+					strncpy(filename, argv[argc - 1], 200);
+					/* security check */
+					checkfilename(filename);
+					/* add the raw path to searchpath */
+					addrawpath(filename);
+					tmp = filename + strlen(filename) - 1;
+					/* later, openinfo automaticaly adds them */
+					strip_compression_suffix(filename);
+					/* get basename */
+					while ((tmp > filename) &&(*tmp != '/'))
+						tmp--;
+					if (*tmp == '/')
+						tmp++;
+					/* and try it without '.info' suffix */
+					id = openinfo(tmp, 0);
+					break;
+				case 'a':
+					use_apropos = 1;
+					break;
+				case 'p':
+					use_apropos = 1;
+					plain_apropos = 1;
+					strncpy(filename, argv[argc - 1], 200);
+					exit(handlemanual(filename));
+					break;
+				case 'c':
+					CutManHeaders = 1;
+					break;
+				case 'd':
+					DontHandleWithoutTagTable = 1;
+					break;
+				case 's':
+					CutEmptyManLines = 1;
+					break;
+			}
+		}
+		while (command_line_option != EOF);
+		/***************************************************************/
+#endif
+
+		checksu();
+		initpaths();
+
+		if (argc > 1)
+		{
+#ifdef HAVE_GETOPT_LONG
+			if (optind < argc)
+			{
+				/* the paths will be searched by openinfo() */
+				strncpy(filename, argv[optind], 200);
+			}
+			else
+			{
+				strcpy(filename, "dir");
+			}
+
+#else
+			/* the paths will be searched by openinfo() */
+			strncpy(filename, argv[argc - 1], 200);
+#endif
+			if (filename[0]=='(')
+			{
+				int fnamelen=strlen(filename);
+				/* erase the leading '(' */
+				for (i=0;i<fnamelen;i++)
+					filename[i]=filename[i+1];
+				for (i=0;filename[i]!=')';i++);
+				/* leave the filename part in filename */
+				filename[i]=0;
+				/* copy the node content to pinfo_start_node */
+				if (!pinfo_start_node)
+				{
+					pinfo_start_node=strdup(&filename[i+1]);
+				}
+			}
+
+			/* security check */
+			checkfilename(filename);
+
+			/* autodetect raw filenames */
+			if ((strncmp(filename,"../",3)==0)||
+					(strncmp(filename,"./",2)==0)||
+					(filename[0]=='/'))
+			{
+				addrawpath(filename);
+			}
+
+			/* leave some space for `.info' suffix */
+			curfile = (char*)xmalloc(strlen(filename) + 100);
+			strcpy(curfile, filename);
+		}
+
+		/* no rawpath has been opened */
+		if (id == NULL)
+			id = openinfo(filename, 0);
+
+		/* try to lookup the name in dir file */
+		if (id == NULL)
+		{
+			id = dirpage_lookup(&type, &message, &lines, filename, &pinfo_start_node);
+		}
+		/* if still nothing, try to use man page instead */
+		if (id == NULL)
+		{
+			printf(_("Error: could not open info file, trying manual\n"));
+			exit(handlemanual(filename));
+		}
+		/* search for indirect entries, if any */
+		if (seek_indirect(id))
+		{
+			read_item(id, &type, &message, &lines);
+			load_indirect(message, lines);
+		}
+
+
+		/* load tag table if such exists... */
+		if (seek_tag_table(id,1) != 2)
+		{
+			if (ForceManualTagTable == 0)
+			{
+				read_item(id, &type, &message, &lines);
+				load_tag_table(message, lines);
+			}
+			else
+			{
+				if (indirect)
+					create_indirect_tag_table();
+				else
+				{
+					fseek(id, SEEK_SET, 0);
+					create_tag_table(id);
+				}
+			}
+		}
+		else /* ...otherwise try to create one */
+		{
+			if ((verbose)&&(strcmp(curfile,"dir")))
+				printf(_("Warning: tag table not found...\n"));
+			if (!DontHandleWithoutTagTable)
+			{
+				if ((verbose)&&(strcmp(curfile,"dir")))
+					printf(_("Trying to create alternate tag table...\n"));
+				create_tag_table(id);
+				/* if there weren't found any info entries */
+				if (TagTableEntries < 1)
+				{
+					printf(_("This doesn't look like info file...\n"));
+					exit(handlemanual(filename));
+				}
+			}
+			else
+				return 1;
+		}
+
+		if (pinfo_start_node)
+		{
+			tag_table_pos = gettagtablepos(pinfo_start_node);
+			if (tag_table_pos == -1)
+			{
+				printf(_("Specified node does not exist...\n"));
+				return 1;
+			}
+		}
+		else
+		{
+			tag_table_pos = gettagtablepos(FirstNodeName);
+		}
+		/* initialize curses screen interface */
+		init_curses();
+
+		do
+		{
+			/* set seek offset for given node */
+			seeknode(tag_table_pos, &id);
+			/* read the node */
+			read_item(id, &type, &message, &lines);
+
+			/* handle goto/link where no file was found -- see bellow */
+			if (!filenotfound)
+				addinfohistory(curfile, tag_table[tag_table_pos].nodename, -1, -1, -1);
+			else
+				filenotfound = 0;
+			work_return_value = work(&message, &type, &lines, id, tag_table_pos);
+			if (work_return_value.node)
+			{
+				/* no cross-file link selected */
+				if (work_return_value.file[0] == 0)
+				{
+					int tmppos = gettagtablepos(work_return_value.node);
+					if (tmppos != -1)
+						tag_table_pos = tmppos;
+				}
+				else /* file was specified */
+				{
+					strip_file_from_info_suffix(work_return_value.file);
+					/* file name was the same with the file currently viewed */
+					if (strcmp(curfile, work_return_value.file) == 0)
+					{
+						int tmppos = gettagtablepos(work_return_value.node);
+						if (tmppos != -1)
+							tag_table_pos = tmppos;
+					}
+					else /* open new info file */
+					{
+						char *tmp;
+						fclose(id);
+						/*tmp = addinfosuffix(work_return_value.file); */
+						tmp = strdup(work_return_value.file);
+						clearfilenameprefix();
+						id = openinfo(tmp, 0);
+						xfree(tmp);
+						tmp = 0;
+						/* if the file doesn't exist */
+						if (id == NULL)
+						{
+							attrset(bottomline);
+							mvhline(maxy - 1, 0, ' ', maxx);
+							mvaddstr(maxy - 1, 0, _("File not found. Press any key..."));
+							move(0, 0);
+							attrset(normal);
+							getch();
+							filenotfound = 1;
+							if (infohistory.length)
+							{
+								npos = infohistory.pos[infohistory.length];
+								ncursor = infohistory.cursor[infohistory.length];
+							}
+							/* open back the old file */
+							strip_file_from_info_suffix(curfile);
+							/*tmp = addinfosuffix(curfile); */
+							tmp = strdup(curfile);
+							id = openinfo(tmp, 0);
+							xfree(tmp);
+							tmp = 0;
+							if (id == NULL)
+							{
+								closeprogram();
+								printf(_("Unexpected error.\n"));
+								return 1;
+							}
+						}
+						else /* if we succeeded in opening new file */
+						{
+							if (curfile)
+							{
+								xfree(curfile);
+								curfile = 0;
+							}
+							curfile = (char*)xmalloc(strlen(work_return_value.file) + 150);
+							strcpy(curfile, work_return_value.file);
+							freeindirect();
+							/* find the indirect entry */
+							if (seek_indirect(id))
+							{
+								/* read it */
+								read_item(id, &type, &message, &lines);
+								/* initialize indirect entries */
+								load_indirect(message, lines);
+							}
+							/* free old tag table */
+							freetagtable();
+							/* search for the new tagtable */
+							if (seek_tag_table(id,0) != 2)
+							{
+								/*
+								 * if no manual initialization requested,
+								 * load the tag table
+								 */
+								if (ForceManualTagTable == 0)
+								{
+									read_item(id, &type, &message, &lines);
+									load_tag_table(message, lines);
+								}
+								else /* create tag table manually */
+								{
+									if (indirect)
+										create_indirect_tag_table();
+									else
+									{
+										fseek(id, SEEK_SET, 0);
+										create_tag_table(id);
+									}
+								}
+							}
+							else /* no tagtable found */
+							{
+								if (!DontHandleWithoutTagTable)
+								{
+									TagTableEntries = 0;
+									mvhline(maxy - 1, 0, ' ', maxx);
+									mvaddstr(maxy - 1, 0, _("Tag table not found. Trying to create alternate..."));
+									create_tag_table(id);
+									if (TagTableEntries < 1)
+									{
+										closeprogram();
+										printf(_("This doesn't look like info file...\n"));
+										return 1;
+									}
+								}
+								else
+									return 1;
+							}
+							if (work_return_value.node[0] != 0)
+							{
+								int tmptagtablepos = gettagtablepos(work_return_value.node);
+								if (tmptagtablepos != -1)
+									tag_table_pos = tmptagtablepos;
+								else
+									tag_table_pos = gettagtablepos(FirstNodeName);
+							}
+							else
+								tag_table_pos = gettagtablepos(FirstNodeName);
+
+						}		/* end: open new info file -- file exists */
+					}		/* end: open new info file */
+				}			/* end: file name was specified */
+			}			/* end: node was specified in work return value */
+		}
+		while (work_return_value.node);
+		fclose(id);
+		closeprogram();
+		/* free's at the end are optional, but look nice :) */
+		freelinks();
+		freeitem(&type, &message, &lines);
+		freetagtable();
+		freeindirect();
+		return 0;
+}
+
+void
+strip_file_from_info_suffix(char *file)
+{
+	if (strlen(file) > 5)
+	{
+		if (strcmp(file + strlen(file) - 5, ".info") == 0)
+		{
+			file = file + strlen(file) - 5;
+			*file = 0;
+		}
+	}
+}
+
+char *
+addinfosuffix(char *info)
+{
+	char *withsuffix = (char*)xmalloc(strlen(info) + 150);
+	strcpy(withsuffix, info);
+	if (strlen(info) == 3)
+	{
+		if (strcmp("dir", info) != 0)
+			strcat(withsuffix, ".info");
+	}
+	else
+		strcat(withsuffix, ".info");
+
+	return withsuffix;
+}
+
+/*
+ * If pinfo was called by root then it should work as nobody.
+ * This protect us against .pso and .open macros which could
+ * be used for breaking the system's security.
+ */
+void
+checksu()
+{
+	struct passwd *pswd;
+	struct group *grwd;
+
+	if (!getegid() || !getgid())
+	{
+		grwd = getgrnam(safe_group);
+		if (!grwd)
+		{
+			if (verbose)
+			{
+				printf(_("Security warning: Unable to get GID of group called: %s\n"), safe_group);
+				sleep(1);
+			}
+		}
+		else
+		{
+			if (!getgid() && !getuid())
+				setgid(grwd->gr_gid);
+			else
+				setegid(grwd->gr_gid);
+		}
+	}
+
+	if (!geteuid() || !getuid())
+	{
+		pswd = getpwnam(safe_user);
+		if (!pswd)
+		{
+			if (verbose)
+			{
+				printf(_("Security warning: Unable to get UID of user called: %s\n"), safe_user);
+				sleep(1);
+			}
+		}
+		else
+		{
+			if (!getuid())
+				setuid(pswd->pw_uid);
+			else
+				seteuid(pswd->pw_uid);
+		}
+	}
+
+}

Deleted: pinfo/branches/cxx/src/printinfo.c

Copied: pinfo/branches/cxx/src/printinfo.cxx (from rev 30, pinfo/branches/cxx/src/printinfo.c)
===================================================================
--- pinfo/branches/cxx/src/printinfo.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/printinfo.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,102 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+
+#include "common_includes.h"
+
+RCSID("$Id$")
+
+/*
+ * Algorithm: We first print highlights, then we send `\r' to the printer,
+ * and we draw the base line. Thus highlights are printed `twice', and
+ * are darker than the rest :)
+ */
+void
+printnode(char ***message, long *lines)
+{
+#define Message	(*message)
+#define Lines	(*lines)
+
+	/* counter, to point at what highlights are already * handled */
+	int highlight = 0;
+	int i, j;
+	/* printer fd */
+	FILE *prnFD;
+	/* temporary buffer */
+	char *buf = (char*)xmalloc(1024);
+
+	prnFD = popen(printutility, "w");
+
+	/* scan through all lines */
+	for (i = 1; i < Lines; i++)
+	{
+		/*
+		 * this says, where the printer's head is
+		 * right now.(offset in cols from the
+		 * beginning of line
+		 */
+		int lineprinted = 0;
+		/*
+		 * let's handle the highlights, which belong to our(i'th) line.
+		 */
+		while (hyperobjects[highlight].line <= i)
+		{
+			/* build a complete highlighted text */
+			if (hyperobjects[highlight].file[0] == 0)
+				strcpy(buf, hyperobjects[highlight].node);
+			else
+			{
+				strcpy(buf, "(");
+				strcat(buf, hyperobjects[highlight].file);
+				strcat(buf, ")");
+				strcat(buf, hyperobjects[highlight].node);
+			}
+			/* if it's a contiunuation of last's line highlight */
+			if (hyperobjects[highlight].line == i - 1)
+			{
+				int length = 1;
+				if (hyperobjects[highlight].breakpos == -1)
+					length = strlen(buf) -
+						hyperobjects[highlight].breakpos;
+				fprintf(prnFD, "%s", buf + length -
+						hyperobjects[highlight].breakpos);
+				lineprinted += strlen(buf + length -
+						hyperobjects[highlight].breakpos);
+			}
+			else if (hyperobjects[highlight].line == i)
+			{
+				for (j = 0; j < hyperobjects[highlight].col - lineprinted; j++)
+					fprintf(prnFD, " ");
+				fprintf(prnFD, "%s", buf);
+				lineprinted = hyperobjects[highlight].col +
+					strlen(buf);
+			}
+			if (highlight < hyperobjectcount - 1)
+				highlight++;
+			else
+				break;
+		}
+		fprintf(prnFD, "\r%s", Message[i]);
+	}
+	pclose(prnFD);
+	xfree(buf);
+#undef Message
+#undef Lines
+}

Deleted: pinfo/branches/cxx/src/readlinewrapper.c

Copied: pinfo/branches/cxx/src/readlinewrapper.cxx (from rev 30, pinfo/branches/cxx/src/readlinewrapper.c)
===================================================================
--- pinfo/branches/cxx/src/readlinewrapper.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/readlinewrapper.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,218 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+#include "common_includes.h"
+
+RCSID("$Id$")
+
+char **rlhistory = 0;
+int rlhistorylen = 0;
+int rlhistorypos = 0;
+
+#define KEY_BCKSPC 8
+
+char *
+readlinewrapper(char *prompt)
+{
+	/* number of keys pressed */
+	int numkeys = 0;
+	/* initial buffer for the read line */
+	char *buf = (char*)xmalloc(1024);
+	/* start coords of input line */
+	int origx, origy;
+	/* cursor position in input string */
+	int cursor = 0;
+	/* key - a variable for getch() */
+	int key = 0, i;
+	/* initial value of line - "" */
+	buf[0] = 0;
+	/* print prompt */
+	addstr(prompt);
+	/* get origx,origy coordinates */
+	getyx(stdscr, origy, origx);
+	/* turn off echoing chars by getch() */
+	noecho();
+	/* create input line bar */
+	mvhline(origy, origx, ' ', maxx - origx);
+
+	/* history entry for this line */
+	rlhistorylen++;
+	/* move history pos to current entry */
+	rlhistorypos = rlhistorylen;
+	/* alloc memory for this entry */
+	if (!rlhistory)
+		rlhistory = (char**)xmalloc(sizeof(char *));
+	else
+		rlhistory = (char**)xrealloc(rlhistory, sizeof(char *) * rlhistorylen);
+	rlhistory[rlhistorylen - 1] = (char*)xmalloc(1024);
+	/* and copy there the current value of input line */
+	strcpy(rlhistory[rlhistorylen - 1], buf);
+	/* call history to be present */
+	if (CallReadlineHistory)
+	{
+		ungetch(KEY_UP);
+		numkeys = -1;
+	}
+
+	while (key != '\n')
+	{
+		/* read key */
+		key = getch();
+		switch(key)
+		{
+			/* move cursor left */
+			case KEY_LEFT:
+				if (cursor > 0)
+					cursor--;
+				break;
+			/* move cursor right */
+			case KEY_RIGHT:
+				if (cursor < strlen(buf))
+					cursor++;
+				break;
+			case KEY_END:
+				cursor = strlen(buf);
+				break;
+			/* handle backspace: copy all */
+			case KEY_BCKSPC:
+			/* chars starting from curpos */
+			case KEY_BACKSPACE:
+				/* - 1 from buf[n+1] to buf   */
+				if (cursor > 0)
+				{
+					for (i = cursor - 1; buf[i] != 0; i++)
+						buf[i] = buf[i + 1];
+					cursor--;
+				}
+				break;
+			/* handle delete key. As above */
+			case KEY_DC:
+				if (cursor <= strlen(buf) - 1)
+				{
+					for (i = cursor; buf[i] != 0; i++)
+						buf[i] = buf[i + 1];
+				}
+				break;
+			/* backwards-history call */
+			case KEY_UP:
+				/* if there is history */
+				if (rlhistorylen)
+					/* and we have */
+					if (rlhistorypos > 1)
+					{			/* where to move */
+						/* decrement history position */
+						rlhistorypos--;
+						/* if the previous pos was the input line */
+						/* save it's value to history */
+						if (rlhistorypos == rlhistorylen - 1)
+							strcpy(rlhistory[rlhistorylen - 1], buf);
+						/*  recall value from history to input buf */
+						strcpy(buf, rlhistory[rlhistorypos - 1]);
+					}
+				cursor = strlen(buf);
+				numkeys = -1;
+				break;
+			/* forwards-history call */
+			case KEY_DOWN:
+				if (rlhistorylen)
+					if (rlhistorypos < rlhistorylen)
+					{
+						rlhistorypos++;
+						strcpy(buf, rlhistory[rlhistorypos - 1]);
+					}
+				cursor = strlen(buf);
+				numkeys = -1;
+				break;
+				/* eliminate nonprintable chars */
+			case '\n':
+			case KEY_PPAGE:
+			case KEY_NPAGE:
+			case KEY_F(1):
+			case KEY_F(2):
+			case KEY_F(3):
+			case KEY_F(4):
+			case KEY_F(5):
+			case KEY_F(6):
+			case KEY_F(7):
+			case KEY_F(8):
+			case KEY_F(9):
+			case KEY_F(10):
+				break;
+			default:
+				if (key >= 32)
+				{
+					/* if this is the first key, delete the buffer */
+					if (numkeys==0 && cursor!=0)
+					{
+						for (i=0; buf[i]!=0; i++)
+							buf[i] = 0;
+						cursor = 0;
+						/* and empty the line */
+						move(origy, origx);
+						for (i = origx; i < maxx; i++)
+							addch(' ');
+						move(origy, origx + cursor);
+					}
+					
+					/* if the cursor is not at the last pos */
+					if (strlen(buf + cursor))
+					{
+						char *tmp = 0;
+						tmp = (char*)xmalloc(strlen(buf + cursor) + 1);
+						strcpy(tmp, buf + cursor);
+						buf[cursor] = key;
+						buf[cursor + 1] = 0;
+						strcat(&buf[cursor + 1], tmp);
+						xfree(tmp);
+						cursor++;
+					}
+					else
+					{
+						buf[cursor + 1] = 0;
+						buf[cursor] = key;
+						cursor++;
+					}
+				}
+		}
+		move(origy, origx);
+		for (i = origx; i < maxx; i++)
+			addch(' ');
+		move(origy, origx);
+		addstr(buf);
+		move(origy, origx + cursor);
+
+		numkeys++;
+
+	}
+	strcpy(rlhistory[rlhistorylen - 1], buf);
+	if (strlen(buf))
+	{
+		rlhistory[rlhistorylen - 1] = (char*)xrealloc(rlhistory[rlhistorylen - 1],
+				strlen(rlhistory[rlhistorylen - 1]) + 1);
+	}
+	else
+	{
+		xfree(rlhistory[rlhistorylen - 1]);
+		rlhistorylen--;
+		rlhistorypos = rlhistorylen;
+	}
+	buf = (char*)xrealloc(buf, strlen(buf) + 1);
+	return buf;
+}

Deleted: pinfo/branches/cxx/src/regexp_search.c

Copied: pinfo/branches/cxx/src/regexp_search.cxx (from rev 30, pinfo/branches/cxx/src/regexp_search.c)
===================================================================
--- pinfo/branches/cxx/src/regexp_search.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/regexp_search.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,180 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+
+#include"common_includes.h"
+
+RCSID("$Id$")
+
+#ifndef ___DONT_USE_REGEXP_SEARCH___
+#include"regex.h"
+#include<ctype.h>
+/* adapted partialy from midnight commander view regexp search */
+
+enum
+{
+	match_file, match_normal
+};
+
+int
+__regexp_search(char *pattern, char *string)
+{
+	int match_type = match_normal;
+	static char *old_pattern = NULL;
+	static int old_type;
+	regmatch_t pmatch[1];
+	int i, flags = REG_ICASE;
+	int rval;
+
+	if (!old_pattern || strcmp(old_pattern, pattern) || old_type != match_type)
+	{
+		if (old_pattern)
+		{
+			free(old_pattern);
+			old_pattern = 0;
+		}
+		for (i = 0; pattern[i] != 0; i++)
+		{
+			if (isupper((unsigned char) pattern[i]))
+			{
+				flags = 0;
+				break;
+			}
+		}
+		flags |= REG_EXTENDED;
+		if (pinfo_re_offset == -1)
+		{
+			pinfo_re_offset = h_regexp_num;
+			if (!h_regexp_num)
+				h_regexp = (regex_t*)malloc(sizeof(regex_t));
+			else
+				h_regexp = (regex_t*)realloc(h_regexp, sizeof(regex_t) *(h_regexp_num + 1));
+		}
+		else
+		{
+			regfree(&h_regexp[pinfo_re_offset]);
+		}
+		/* invalid regexp */
+		if (regcomp(&h_regexp[pinfo_re_offset], pattern, flags))
+		{
+			return 0;
+		}
+		old_pattern = strdup(pattern);
+		old_type = match_type;
+	}
+	rval = regexec(&h_regexp[pinfo_re_offset], string, 1, pmatch, 0);
+	if (rval != 0)
+		return -1;
+	else
+		return pmatch[0].rm_so;
+}
+
+int
+regexp_search(char *pattern, char *string)
+{
+	int newlines = 0, ptr_offset = -1;
+	char *__newlines[2];
+	char *str = string;
+	char *start = str;
+	while (*str)
+	{
+		if (*str == '\n')
+		{
+			__newlines[newlines] = str + 1;
+			newlines++;
+		}
+		if (newlines == 2)
+		{
+			*str = 0;
+			ptr_offset = __regexp_search(pattern, start);
+			*str = '\n';
+			newlines = 1;
+			if (ptr_offset != -1)
+				return (start - string) + ptr_offset;
+			if (*(__newlines[0] + 1) != 0)
+				start = __newlines[0] + 1;
+			if (ptr_offset == -1)
+			{
+				__newlines[0] = __newlines[1];
+			}
+		}
+		str++;
+	}
+	ptr_offset = __regexp_search(pattern, start);
+	if (ptr_offset != -1)
+	{
+		return (start - string) + ptr_offset;
+	}
+	else
+		return -1;
+}
+#else /* non-regexp version of search */
+int
+__regexp_search(char *pattern, char *string)
+{
+	char *found = strstr(string, pattern);
+	if (found == NULL)
+		return -1;
+	else
+		return (long)(found - string);
+}
+
+int
+regexp_search(char *pattern, char *string)
+{
+	int newlines = 0, ptr_offset = -1;
+	char *found;
+	char *__newlines[2];
+	char *str = string;
+	char *start = str;
+	while (*str)
+	{
+		if (*str == '\n')
+		{
+			__newlines[newlines] = str + 1;
+			newlines++;
+		}
+		if (newlines == 2)
+		{
+			*str = 0;
+			ptr_offset = __regexp_search(pattern, start);
+			*str = '\n';
+			newlines = 1;
+			if (ptr_offset != -1)
+				return (start - string) + ptr_offset;
+			if (*(__newlines[0] + 1) != 0)
+				start = __newlines[0] + 1;
+			if (ptr_offset == -1)
+			{
+				__newlines[0] = __newlines[1];
+			}
+		}
+		str++;
+	}
+	ptr_offset = __regexp_search(pattern, start);
+	if (ptr_offset != -1)
+	{
+		return (start - string) + ptr_offset;
+	}
+	else
+		return -1;
+}
+
+#endif

Deleted: pinfo/branches/cxx/src/sigblock.c

Copied: pinfo/branches/cxx/src/sigblock.cxx (from rev 30, pinfo/branches/cxx/src/sigblock.c)

Deleted: pinfo/branches/cxx/src/signal_handler.c

Copied: pinfo/branches/cxx/src/signal_handler.cxx (from rev 30, pinfo/branches/cxx/src/signal_handler.c)

Deleted: pinfo/branches/cxx/src/snprintf.c

Copied: pinfo/branches/cxx/src/snprintf.cxx (from rev 30, pinfo/branches/cxx/src/snprintf.c)

Deleted: pinfo/branches/cxx/src/utils.c

Copied: pinfo/branches/cxx/src/utils.cxx (from rev 30, pinfo/branches/cxx/src/utils.c)
===================================================================
--- pinfo/branches/cxx/src/utils.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/utils.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,520 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+
+#include "common_includes.h"
+
+RCSID("$Id$")
+
+#include <regex.h>
+#include <ctype.h>
+
+char *safe_user = "nobody";
+char *safe_group = "nobody";
+
+#ifndef HAVE_CURS_SET
+void
+curs_set(int a)
+{
+}
+#endif
+
+#ifdef ___DONT_USE_REGEXP_SEARCH___
+char *pinfo_re_pattern = 0;
+#else
+int pinfo_re_offset = -1;
+#endif
+
+#ifdef HAS_READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <term.h>
+/* HAS_READLINE */
+#endif
+
+
+/*
+ * the bellow define enables malloc/realloc/free logging to stderr.
+ * They start to log their argument values.
+ *
+ * #define ___DEBUG___
+ *
+ */
+
+#ifdef ___DEBUG___
+unsigned long malloc_addr[1000];
+unsigned long msizes[1000];
+long addrescount = 0;
+/* ___DEBUG___ */
+#endif
+
+
+int curses_open = 0;
+
+int shell_cursor = 1;
+
+void
+xfree(void *ptr)
+{
+#ifdef ___DEBUG___
+	int i, j;
+	int flag = 0;
+	unsigned long msize = 0;
+	for (i = 0; i < addrescount; i++)
+		msize += msizes[i];
+	fprintf(stderr, "Size: %lu, count: %ld, freeing %lu\n", msize, addrescount,(unsigned long) ptr);
+	for (i = 0; i < addrescount; i++)
+		if (malloc_addr[i] ==(unsigned long) ptr)
+		{
+			flag = 1;
+			for (j = i + 1; j < addrescount; j++)
+			{
+				malloc_addr[j - 1] = malloc_addr[j];
+				msizes[j - 1] = msizes[j];
+			}
+			addrescount--;
+			break;
+		}
+	if (flag == 0)
+	{
+		fprintf(stderr, "ERROR!!!\n");
+		getchar();
+	}
+/* ___DEBUG___ */
+#endif
+	free(ptr);
+}
+
+void *
+xmalloc(size_t size)
+{
+	register void *value = malloc(size);
+#ifdef ___DEBUG___
+	unsigned long msize = 0;
+	int i;
+/* ___DEBUG___ */
+#endif
+	if (value == 0)
+	{
+		closeprogram();
+		printf(_("Virtual memory exhausted\n"));
+		exit(1);
+	}
+#ifdef ___DEBUG___
+	for (i = 0; i < addrescount; i++)
+		msize += msizes[i];
+	fprintf(stderr, "Size %lu, count: %ld, allocated %lu\n", msize, addrescount,(unsigned long) value);
+	malloc_addr[addrescount] =(unsigned long) value;
+	msizes[addrescount] = size;
+	if (addrescount < 1000)
+		addrescount++;
+	else
+	{
+		fprintf(stderr, "trace buffer exhausted\n");
+	}
+/* ___DEBUG___ */
+#endif
+	memset(value, 0, size);
+	return value;
+}
+
+void *
+xrealloc(void *ptr, size_t size)
+{
+#ifdef ___DEBUG___
+	int i, j, flag = 0;
+	register void *value;
+	unsigned long msize = 0;
+	for (i = 0; i < addrescount; i++)
+		msize += msizes[i];
+	fprintf(stderr, "Size: %lu, count: %ld, reallocating %lu to ", msize, addrescount,(unsigned long) ptr);
+	for (i = 0; i < addrescount; i++)
+		if (malloc_addr[i] ==(unsigned long) ptr)
+		{
+			flag = 1;
+			for (j = i + 1; j < addrescount; j++)
+			{
+				malloc_addr[j - 1] = malloc_addr[j];
+				msizes[j - 1] = msizes[j];
+			}
+			addrescount--;
+			break;
+		}
+	if (flag == 0)
+	{
+		fprintf(stderr, "ERROR!!!\n");
+		getchar();
+	}
+	value = realloc(ptr, size);
+#else
+	register void *value = realloc(ptr, size + 1024);
+/* ___DEBUG___ */
+#endif
+	if (value == 0)
+	{
+		closeprogram();
+		printf(_("Virtual memory exhausted\n"));
+		exit(1);
+	}
+#ifdef ___DEBUG___
+	fprintf(stderr, "%lu, with size %lu\n",(unsigned long) value,(unsigned long) size);
+	malloc_addr[addrescount] =(unsigned long) value;
+	msizes[addrescount] = size;
+	if (addrescount < 1000)
+		addrescount++;
+	else
+	{
+		fprintf(stderr, "trace buffer exhausted\n");
+	}
+/* ___DEBUG___ */
+#endif
+	return value;
+}
+
+void
+initlocale()
+{
+#ifdef ___DEBUG___
+	int i;
+	for (i = 0; i < 1000; i++)
+		malloc_addr[i] = 0;
+/* ___DEBUG___ */
+#endif
+	sbrk(100000);
+	setlocale(LC_ALL, "");
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
+}
+
+void
+mymvhline(int y, int x, char ch, int len)
+{
+	int i;
+	for (i = 0; i < len; i++)
+		mvaddch(y, x + i, ch);
+}
+
+void
+checkfilename(char *filename)
+{
+	if ((strchr(filename, '<')) ||
+			(strchr(filename, '>')) ||
+			(strchr(filename, '|')) ||
+			(strchr(filename, '(')) ||
+			(strchr(filename, ')')) ||
+			(strchr(filename, '!')) ||
+			(strchr(filename, '`')) ||
+			(strchr(filename, '&')) ||
+			(strchr(filename, ';')))
+	{
+		printf(_("Illegal characters in filename!\n*** %s\n"), filename);
+		exit(1);
+	}
+}
+
+#ifdef HAS_READLINE
+/* custom function that readline will use to display text */
+void
+my_rl_display()
+{
+	/* go to the bottom line, empty it, and print the prompt and buffer */
+	attrset(bottomline);
+	mymvhline(maxy - 1, 0, ' ', maxx);
+	move(maxy-1,0);
+	printw("%s%s", rl_prompt, rl_line_buffer);
+	refresh();
+}
+#endif
+
+char *
+getstring(char *prompt)
+{
+	char *buf;
+
+#ifdef HAS_READLINE
+
+	curs_set(1);
+	move(maxy - 1, 0);
+	refresh();
+
+	rl_readline_name = PACKAGE;
+	
+	/* set display function for readline to my_rl_display and call readline */
+	rl_redisplay_function = my_rl_display;
+	buf = readline(prompt);
+	if (buf && *buf) 
+		add_history(buf);
+	
+	curs_set(0);
+
+#else
+
+	move(maxy - 1, 0);
+	buf = readlinewrapper(prompt);
+
+#endif
+
+	return buf;
+}
+
+void
+init_curses()
+{
+	initscr();
+	noecho();
+	cbreak();
+	keypad(stdscr, TRUE);
+	/*  meta(stdscr, TRUE); */
+	initcolors();
+	shell_cursor = curs_set(0);
+#ifdef NCURSES_MOUSE_VERSION
+	mousemask(BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED, NULL);
+/* NCURSES_MOUSE_VERSION */
+#endif
+	curses_open = 1;
+}
+
+
+void
+closeprogram()
+{
+	if (curses_open)
+		myendwin();
+	if (ClearScreenAtExit)
+		system("clear");
+	else
+		printf("\n");
+	if (tmpfilename1)
+	{
+		unlink(tmpfilename1);
+		xfree(tmpfilename1);
+	}
+	if (tmpfilename2)
+	{
+		unlink(tmpfilename2);
+		xfree(tmpfilename2);
+	}
+}
+
+int
+gettagtablepos_search_internal(char *node, int left, int right)
+{
+	/* left+(right-left)/2 */
+	int thispos = left +((right - left) >> 1);
+	int compare_result = compare_tag_table_string(tag_table[thispos].nodename, node);
+	if (compare_result == 0)
+		return thispos;
+	else
+	{
+		if (left == right)
+			return -1;
+		if (compare_result > 0)
+		{
+			if (thispos > left)
+				return gettagtablepos_search_internal(node, left, thispos - 1);
+			else
+				return -1;
+		}
+		else if (compare_result < 0)
+		{
+			if (thispos < right)
+				return gettagtablepos_search_internal(node, thispos + 1, right);
+			else
+				return -1;
+		}
+	}
+	return -1;
+}
+
+int
+gettagtablepos(char *node)
+{
+	/* strip spaces from the beginning */
+	while (1)
+	{
+		if ((*node != ' ') &&(*node != '\t'))
+			break;
+		node++;
+	}
+	return gettagtablepos_search_internal(node, 1, TagTableEntries);
+}
+
+int
+pinfo_getch()
+{
+	int key = getch();
+	/* following key will be alt's value */
+	if (key == META_KEY)
+	{
+		key = getch();
+		key |= 0x200;
+	}
+	return key;
+}
+
+void
+waitforgetch()
+{
+	fd_set rdfs;
+	FD_ZERO(&rdfs);
+	FD_SET(0, &rdfs);
+	select(1, &rdfs, NULL, NULL, NULL);
+}
+
+/* returns 0 on success, 1 on error */
+int
+pinfo_re_comp(char *name)
+{
+#ifdef ___DONT_USE_REGEXP_SEARCH___
+	if (pinfo_re_pattern)
+	{
+		free(pinfo_re_pattern);
+		pinfo_re_pattern = 0;
+	}
+	pinfo_re_pattern = strdup(name);
+	return 0;
+#else
+	if (pinfo_re_offset == -1)
+	{
+		pinfo_re_offset = h_regexp_num;
+		if (!h_regexp_num)
+			h_regexp = (regex_t*)malloc(sizeof(regex_t));
+		else
+			h_regexp = (regex_t*)realloc(h_regexp, sizeof(regex_t) *(h_regexp_num + 1));
+	}
+	else
+	{
+		regfree(&h_regexp[pinfo_re_offset]);
+	}
+	return regcomp(&h_regexp[pinfo_re_offset], name, REG_ICASE);
+#endif
+}
+
+int
+pinfo_re_exec(char *name)
+{
+#ifdef ___DONT_USE_REGEXP_SEARCH___
+	char *found;
+	if (pinfo_re_pattern)
+	{
+		found = strstr(name, pinfo_re_pattern);
+		if (found != NULL)
+			return 1;
+		else
+			return 0;
+	}
+#else
+	regmatch_t pmatch[1];
+	return !regexec(&h_regexp[pinfo_re_offset], name, 1, pmatch, 0);
+#endif
+}
+
+int
+yesno(char *prompt, int def)
+{
+	char *yes = _("yes");
+	char *no = _("no");
+	int key;
+
+	attrset(bottomline);
+	mymvhline(maxy - 1, 0, ' ', maxx);
+	move(maxy - 1, 0);
+	/* if default answer is yes */
+	if (def)
+		printw("%s([%c]/%c)", prompt, *yes, *no);
+	else
+		printw("%s([%c]/%c)", prompt, *no, *yes);
+	nodelay(stdscr, FALSE);
+	while (1)
+	{
+		key = getch();
+		if (key == ERR)
+			return -1;
+		if (is_enter_key(key))
+			break;
+		else
+		{
+			if (tolower(key) == tolower(*yes))
+			{
+				def = 1;
+				break;
+			}
+			else
+			{
+				if (tolower(key) == tolower(*no))
+				{
+					def = 0;
+					break;
+				}
+				else
+					beep();
+			}
+		}
+	}
+
+	nodelay(stdscr, TRUE);
+	if (def)
+		addstr(yes);
+	else
+		addstr(no);
+	attrset(normal);
+	return def;
+}
+
+void
+myclrtoeol()
+{
+	int x, y, i;
+	getyx(stdscr, y, x);
+	for (i = x; i < maxx; i++)
+		mvaddch(y, i, ' ');
+}
+
+void
+copy_stripped_from_regexp(char *src, char *dest)
+{
+	char *forbidden = "*.\\()[]\n";
+	while (strchr(forbidden, *src) == NULL)
+	{
+		if (*src == 0)
+			break;
+		*dest = *src;
+		src++;
+		dest++;
+	}
+	*dest = 0;
+}
+
+void
+myendwin()
+{
+	curs_set(shell_cursor);
+	endwin();
+}
+
+void
+handlewinch()
+{
+	myendwin();
+	init_curses();
+	doupdate();
+	getmaxyx(stdscr, maxy, maxx);
+	ungetch(keys.refresh_1);
+}

Modified: pinfo/branches/cxx/src/utils.h
===================================================================
--- pinfo/branches/cxx/src/utils.h	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/utils.h	2005-08-22 21:00:13 UTC (rev 31)
@@ -73,6 +73,9 @@
 /* Block until something's on STDIN */
 void waitforgetch ();
 
+/* Handle SIGWINCH */
+void handlewinch ();
+
 /* is curses screen open? */
 extern int curses_open;
 

Deleted: pinfo/branches/cxx/src/video.c

Copied: pinfo/branches/cxx/src/video.cxx (from rev 30, pinfo/branches/cxx/src/video.c)
===================================================================
--- pinfo/branches/cxx/src/video.c	2005-08-22 20:01:39 UTC (rev 30)
+++ pinfo/branches/cxx/src/video.cxx	2005-08-22 21:00:13 UTC (rev 31)
@@ -0,0 +1,292 @@
+/***************************************************************************
+ *  Pinfo is a ncurses based lynx style info documentation browser
+ *
+ *  Copyright (C) 1999  Przemek Borys <pborys at dione.ids.pl>
+ *  Copyright (C) 2005  Bas Zoetekouw <bas at debian.org>
+ *  Copyright 2005  Nathanael Nerode <neroden at gcc.gnu.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ ***************************************************************************/
+
+
+#include "common_includes.h"
+
+RCSID("$Id$")
+
+void info_add_highlights(int pos, int cursor, long lines, int column, char **message);
+
+void
+substitutestr(char *src, char *dest, char *from, char *to)
+	/*
+	 * Utility for substituting strings in given string.
+	 * Used for internationalization of info headers.
+	 */
+{
+	char *start = strstr(src, from);
+	char tmp;
+	if (!start)
+		strcpy(dest, src);
+	else
+	{
+		tmp = *start;
+		*start = 0;
+		strcpy(dest, src);
+		strcat(dest, to);
+		*start = tmp;
+		start += strlen(from);
+		strcat(dest, start);
+	}
+}
+
+void
+addtopline(char *type, int column)
+{
+	char *buf1 = (char*)xmalloc(strlen(type) + 50);
+	char *buf2 = (char*)xmalloc(strlen(type) + 50);
+	int buf2len;
+	strcpy(buf1, type);
+
+	substitutestr(buf1, buf2, "File:", _("File:"));
+	substitutestr(buf2, buf1, "Node:", _("Node:"));
+	substitutestr(buf1, buf2, "Next:", _("Next:"));
+	substitutestr(buf2, buf1, "Prev:", _("Prev:"));
+	substitutestr(buf1, buf2, "Up:", _("Up:"));
+	attrset(topline);
+	mymvhline(0, 0, ' ', maxx);	/* pads line with spaces -- estetic */
+	buf2len=strlen(buf2);
+	if (buf2len)
+		buf2[buf2len - 1] = '\0';
+	if (buf2len>column)
+		mvaddstr(0, 0, buf2+column);
+	attrset(normal);
+	xfree(buf1);
+	xfree(buf2);
+}
+
+void
+showscreen(char **message, char *type, long lines, long pos, long cursor, int column)
+{
+	long i;
+#ifdef getmaxyx
+	getmaxyx(stdscr, maxy, maxx);
+#endif
+#ifdef HAVE_BKGDSET
+	bkgdset(' ' | normal);
+#endif
+	attrset(normal);
+	for (i = pos;(i < lines) &&(i < pos + maxy - 2); i++)
+	{
+		int tmp = strlen(message[i]) - 1;
+		message[i][tmp] = 0;
+		if (tmp>column)
+			mvaddstr(i + 1 - pos, 0, message[i]+column);
+		else
+			move(i + 1 - pos,0);
+#ifdef HAVE_BKGDSET
+		clrtoeol();
+#else
+		myclrtoeol();
+#endif
+		message[i][tmp] = '\n';
+	}
+	clrtobot();
+#ifdef HAVE_BKGDSET
+	bkgdset(0);
+#endif
+	attrset(bottomline);
+	mymvhline(maxy - 1, 0, ' ', maxx);
+	move(maxy - 1, 0);
+	if ((pos < lines - 1) &&(lines > pos + maxy - 2))
+		printw(_("Viewing line %d/%d, %d%%"), pos + maxy - 2, lines,((pos + maxy - 2) * 100) / lines);
+	else
+		printw(_("Viewing line %d/%d, 100%%"), lines, lines);
+	info_add_highlights(pos, cursor, lines, column, message);
+	attrset(normal);
+	move(0, 0);
+	refresh();
+}
+
+/*
+ * prints a line, taking care for the horizontal scrolling.
+ *  if the string fits in the window, it is drawn. If not,
+ *  it is either cut, or completely omitted.
+ */
+void
+info_addstr(int y, int x, char *txt, int column, int txtlen)
+{
+  int maxy, maxx;
+  getmaxyx(stdscr, maxy, maxx);
+  /* Use maxx and mvaddnstr to force clipping.
+   * Fairly blunt instrument, but the best I could come up with.
+   * Breaks in the presence of tabs; I don't see how to handle them. */
+	if (x>column)
+		mvaddnstr(y,x-column,txt, maxx-(x-column) );
+	else if (x+txtlen>column)
+		mvaddnstr(y,0,txt+(column-x), maxx );
+#ifdef __DEBUG__
+  refresh();
+#endif /* __DEBUG__ */
+}
+
+void
+info_add_highlights(int pos, int cursor, long lines, int column, char **message)
+{
+	int i, j;
+	for (i = 0; i < hyperobjectcount; i++)
+	{
+		if ((hyperobjects[i].line >= pos) &&
+				(hyperobjects[i].line < pos +(maxy - 2)))
+		{
+			/* first part of if's sets the required attributes */
+			if (hyperobjects[i].type < 2)		/* menu */
+			{
+				if (i == cursor)
+					attrset(menuselected);
+				else
+					attrset(menu);
+			}
+			else if (hyperobjects[i].type < 4)	/* note */
+			{
+				if (i == cursor)
+					attrset(noteselected);
+				else
+					attrset(note);
+			}
+			else if (hyperobjects[i].type < HIGHLIGHT)	/* url */
+			{
+				if (i == cursor)
+					attrset(urlselected);
+				else
+					attrset(url);
+			}
+			else /* quoted text -- highlight it */
+			{
+				attrset(infohighlight);
+			}
+			/* now we start actual drawing */
+			if (hyperobjects[i].file[0] == 0)
+			{
+				if (hyperobjects[i].breakpos == -1)
+				{
+					info_addstr(1 + hyperobjects[i].line - pos,
+							hyperobjects[i].col,
+							hyperobjects[i].node,
+							column,
+							hyperobjects[i].nodelen);
+
+				}
+				else
+				{
+					char tmp = hyperobjects[i].node[hyperobjects[i].breakpos];
+					hyperobjects[i].node[hyperobjects[i].breakpos] = 0;
+					info_addstr(1 + hyperobjects[i].line - pos,
+							hyperobjects[i].col,
+							hyperobjects[i].node,
+							column,
+							hyperobjects[i].breakpos);
+					hyperobjects[i].node[hyperobjects[i].breakpos] = tmp;
+					j = hyperobjects[i].breakpos;
+					/* skip leading spaces after newline */
+					while (hyperobjects[i].node[j] == ' ')
+						j++;
+					if (hyperobjects[i].line - pos + 3 < maxy)
+						info_addstr(1 + hyperobjects[i].line - pos + 1,
+								j - hyperobjects[i].breakpos,
+								hyperobjects[i].node + j,
+								column,
+								hyperobjects[i].nodelen-j);
+				}
+			}
+			else
+			{
+				if (hyperobjects[i].breakpos == -1)
+				{
+					char *buf=(char*)xmalloc(hyperobjects[i].filelen+hyperobjects[i].nodelen+3);
+					snprintf(buf,hyperobjects[i].filelen+hyperobjects[i].nodelen+3,
+							"(%s)%s",hyperobjects[i].file,hyperobjects[i].node);
+					info_addstr(1 + hyperobjects[i].line - pos,
+							hyperobjects[i].col,
+							buf,
+							column,
+							hyperobjects[i].filelen+hyperobjects[i].nodelen+2);
+					xfree(buf);
+				}
+				else
+				{
+					static char buf[1024];
+					char tmp;
+					strcpy(buf, "(");
+					strcat(buf, hyperobjects[i].file);
+					strcat(buf, ")");
+					strcat(buf, hyperobjects[i].node);
+					tmp = buf[hyperobjects[i].breakpos];
+					buf[hyperobjects[i].breakpos] = 0;
+					info_addstr(1 + hyperobjects[i].line - pos,
+							hyperobjects[i].col,
+							buf,
+							column,
+							hyperobjects[i].breakpos+2);
+					buf[hyperobjects[i].breakpos] = tmp;
+					j = hyperobjects[i].breakpos;
+					/* skip leading spaces after newline */
+					while (buf[j] == ' ')
+						j++;
+					if (hyperobjects[i].line - pos + 3 < maxy)
+						info_addstr(1 + hyperobjects[i].line - pos + 1,
+								j - hyperobjects[i].breakpos,
+								buf + j,
+								column,
+								hyperobjects[i].filelen+hyperobjects[i].nodelen+2-j);
+				}
+			}
+			attrset(normal);
+		}
+	}
+#ifndef ___DONT_USE_REGEXP_SEARCH___
+	if ((h_regexp_num) ||(aftersearch))
+	{
+		regmatch_t pmatch[1];
+		long maxpos = pos +(maxy - 2);
+		if (maxpos > lines)
+			maxpos = lines;
+		for (i = pos; i < maxpos; i++)
+		{
+			int maxregexp = aftersearch ? h_regexp_num + 1 : h_regexp_num;
+			/*
+			 * if it is after search, then we have user defined regexps+
+			 * a searched regexp to highlight
+			 */
+			for (j = 0; j < maxregexp; j++)
+			{
+				char *str = message[i];
+				while (!regexec(&h_regexp[j], str, 1, pmatch, 0))
+				{
+					int n = pmatch[0].rm_eo - pmatch[0].rm_so, k;
+					int y = i - pos + 1, x = calculate_len(message[i], pmatch[0].rm_so + str);
+					int txtoffset = pmatch[0].rm_so + str - message[i];
+					char tmp;
+					tmp = message[i][x + n];
+					message[i][x + n] = 0;
+					attrset(searchhighlight);
+					mvaddstr(y, x, message[i] + txtoffset);
+					attrset(normal);
+					message[i][x + n] = tmp;
+					str = str + pmatch[0].rm_eo;
+				}
+			}
+		}
+	}
+#endif
+}




More information about the Pinfo-devel mailing list