summaryrefslogtreecommitdiff
path: root/alpine/osdep
diff options
context:
space:
mode:
authorEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
committerEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
commit094ca96844842928810f14844413109fc6cdd890 (patch)
treee60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /alpine/osdep
downloadalpine-094ca96844842928810f14844413109fc6cdd890.tar.xz
Initial Alpine Version
Diffstat (limited to 'alpine/osdep')
-rw-r--r--alpine/osdep/Makefile.am22
-rw-r--r--alpine/osdep/Makefile.in544
-rw-r--r--alpine/osdep/ReadMe14
-rw-r--r--alpine/osdep/alpine-splash.bmpbin0 -> 532014 bytes
-rw-r--r--alpine/osdep/alpine.icobin0 -> 3262 bytes
-rw-r--r--alpine/osdep/chnge_pw.c65
-rw-r--r--alpine/osdep/chnge_pw.h25
-rw-r--r--alpine/osdep/debuging.c604
-rw-r--r--alpine/osdep/debuging.h30
-rw-r--r--alpine/osdep/diskquot78
-rw-r--r--alpine/osdep/diskquot.a328
-rw-r--r--alpine/osdep/diskquot.a416
-rw-r--r--alpine/osdep/diskquot.hpp9
-rw-r--r--alpine/osdep/diskquot.non.c46
-rw-r--r--alpine/osdep/diskquot.ptx9
-rw-r--r--alpine/osdep/diskquot.sgi8
-rw-r--r--alpine/osdep/diskquot.so59
-rw-r--r--alpine/osdep/diskquot.sun8
-rw-r--r--alpine/osdep/diskquot.sv49
-rw-r--r--alpine/osdep/execview.c555
-rw-r--r--alpine/osdep/execview.h27
-rw-r--r--alpine/osdep/fltrname.c119
-rw-r--r--alpine/osdep/fltrname.h26
-rw-r--r--alpine/osdep/jobcntrl.c55
-rw-r--r--alpine/osdep/jobcntrl.h25
-rw-r--r--alpine/osdep/makefile.wnt66
-rw-r--r--alpine/osdep/mclosed.icobin0 -> 3262 bytes
-rw-r--r--alpine/osdep/mswin.def17
-rw-r--r--alpine/osdep/mswin.rc605
-rw-r--r--alpine/osdep/mswinver.c74
-rw-r--r--alpine/osdep/newmail.icobin0 -> 3262 bytes
-rw-r--r--alpine/osdep/print.c529
-rw-r--r--alpine/osdep/print.h28
-rw-r--r--alpine/osdep/resource.h1
-rw-r--r--alpine/osdep/solquota174
-rw-r--r--alpine/osdep/sunquota136
-rw-r--r--alpine/osdep/termin.gen.c1252
-rw-r--r--alpine/osdep/termin.gen.h48
-rw-r--r--alpine/osdep/termin.unx.c752
-rw-r--r--alpine/osdep/termin.unx.h29
-rw-r--r--alpine/osdep/termin.wnt.c352
-rw-r--r--alpine/osdep/termin.wnt.h32
-rw-r--r--alpine/osdep/termout.gen.c584
-rw-r--r--alpine/osdep/termout.gen.h54
-rw-r--r--alpine/osdep/termout.unx.c1002
-rw-r--r--alpine/osdep/termout.unx.h24
-rw-r--r--alpine/osdep/termout.win127
-rw-r--r--alpine/osdep/termout.wnt.c1862
-rw-r--r--alpine/osdep/termout.wnt.h47
-rw-r--r--alpine/osdep/windlg.h10
50 files changed, 10106 insertions, 0 deletions
diff --git a/alpine/osdep/Makefile.am b/alpine/osdep/Makefile.am
new file mode 100644
index 00000000..7c1547d4
--- /dev/null
+++ b/alpine/osdep/Makefile.am
@@ -0,0 +1,22 @@
+## Process this file with automake to produce Makefile.in
+## Use aclocal -I m4; automake
+
+# ========================================================================
+# Copyright 2006 University of Washington
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# ========================================================================
+
+noinst_LIBRARIES = libpineosd.a
+
+libpineosd_a_SOURCES = chnge_pw.c debuging.c diskquot.non.c execview.c fltrname.c \
+ jobcntrl.c print.c termin.gen.c termin.unx.c termout.gen.c termout.unx.c \
+ debuging.h execview.h fltrname.h jobcntrl.h print.h resource.h termin.gen.h \
+ termin.unx.h termout.gen.h termout.unx.h windlg.h
+
+AM_CPPFLAGS = -I@top_builddir@/include -I@top_srcdir@/include
diff --git a/alpine/osdep/Makefile.in b/alpine/osdep/Makefile.in
new file mode 100644
index 00000000..4d452c9f
--- /dev/null
+++ b/alpine/osdep/Makefile.in
@@ -0,0 +1,544 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# ========================================================================
+# Copyright 2006 University of Washington
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# ========================================================================
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = alpine/osdep
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \
+ $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/VERSION \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/include/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+libpineosd_a_AR = $(AR) $(ARFLAGS)
+libpineosd_a_LIBADD =
+am_libpineosd_a_OBJECTS = chnge_pw.$(OBJEXT) debuging.$(OBJEXT) \
+ diskquot.non.$(OBJEXT) execview.$(OBJEXT) fltrname.$(OBJEXT) \
+ jobcntrl.$(OBJEXT) print.$(OBJEXT) termin.gen.$(OBJEXT) \
+ termin.unx.$(OBJEXT) termout.gen.$(OBJEXT) \
+ termout.unx.$(OBJEXT)
+libpineosd_a_OBJECTS = $(am_libpineosd_a_OBJECTS)
+DEFAULT_INCLUDES =
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libpineosd_a_SOURCES)
+DIST_SOURCES = $(libpineosd_a_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CP = @CP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+C_CLIENT_CFLAGS = @C_CLIENT_CFLAGS@
+C_CLIENT_GCCOPTLEVEL = @C_CLIENT_GCCOPTLEVEL@
+C_CLIENT_LDFLAGS = @C_CLIENT_LDFLAGS@
+C_CLIENT_SPECIALS = @C_CLIENT_SPECIALS@
+C_CLIENT_TARGET = @C_CLIENT_TARGET@
+C_CLIENT_WITH_IPV6 = @C_CLIENT_WITH_IPV6@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+ISPELLPROG = @ISPELLPROG@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN = @LN@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKE = @MAKE@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NPA_PROG = @NPA_PROG@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PWPROG = @PWPROG@
+RANLIB = @RANLIB@
+REGEX_BUILD = @REGEX_BUILD@
+RM = @RM@
+SED = @SED@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPELLPROG = @SPELLPROG@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WEB_BINDIR = @WEB_BINDIR@
+WEB_BUILD = @WEB_BUILD@
+WEB_PUBCOOKIE_BUILD = @WEB_PUBCOOKIE_BUILD@
+WEB_PUBCOOKIE_LIB = @WEB_PUBCOOKIE_LIB@
+WEB_PUBCOOKIE_LINK = @WEB_PUBCOOKIE_LINK@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+acx_pthread_config = @acx_pthread_config@
+alpine_interactive_spellcheck = @alpine_interactive_spellcheck@
+alpine_simple_spellcheck = @alpine_simple_spellcheck@
+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@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LIBRARIES = libpineosd.a
+libpineosd_a_SOURCES = chnge_pw.c debuging.c diskquot.non.c execview.c fltrname.c \
+ jobcntrl.c print.c termin.gen.c termin.unx.c termout.gen.c termout.unx.c \
+ debuging.h execview.h fltrname.h jobcntrl.h print.h resource.h termin.gen.h \
+ termin.unx.h termout.gen.h termout.unx.h windlg.h
+
+AM_CPPFLAGS = -I@top_builddir@/include -I@top_srcdir@/include
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(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 ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign alpine/osdep/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign alpine/osdep/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @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
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libpineosd.a: $(libpineosd_a_OBJECTS) $(libpineosd_a_DEPENDENCIES)
+ -rm -f libpineosd.a
+ $(libpineosd_a_AR) libpineosd.a $(libpineosd_a_OBJECTS) $(libpineosd_a_LIBADD)
+ $(RANLIB) libpineosd.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chnge_pw.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debuging.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diskquot.non.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execview.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fltrname.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jobcntrl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/termin.gen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/termin.unx.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/termout.gen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/termout.unx.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/alpine/osdep/ReadMe b/alpine/osdep/ReadMe
new file mode 100644
index 00000000..787b9b71
--- /dev/null
+++ b/alpine/osdep/ReadMe
@@ -0,0 +1,14 @@
+The os-xxx.h files are created totally by hand. Start with os-gen.h,
+the generic version of the os.h file.
+
+The os-xxx.c files may be created by hand or you may use the simple include
+method that is used here. The os.c files are made by creating an
+os-xxx.ic file which lists all of the files it includes, and then
+running make os-xxx.c. There is an os-gen.ic generic version of the
+.ic file.
+
+You will also need to create a makefile.xxx in the parent directory. There
+are other makefiles to inspect there, including a generic makefile.gen.
+
+The names of all the included files here have to be eight characters or less
+for DOS, hence the stupid names.
diff --git a/alpine/osdep/alpine-splash.bmp b/alpine/osdep/alpine-splash.bmp
new file mode 100644
index 00000000..0bd797be
--- /dev/null
+++ b/alpine/osdep/alpine-splash.bmp
Binary files differ
diff --git a/alpine/osdep/alpine.ico b/alpine/osdep/alpine.ico
new file mode 100644
index 00000000..d6b7af76
--- /dev/null
+++ b/alpine/osdep/alpine.ico
Binary files differ
diff --git a/alpine/osdep/chnge_pw.c b/alpine/osdep/chnge_pw.c
new file mode 100644
index 00000000..e16e5983
--- /dev/null
+++ b/alpine/osdep/chnge_pw.c
@@ -0,0 +1,65 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: chnge_pw.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#include <system.h> /* os-dep defs/includes */
+#include <general.h> /* generally useful definitions */
+
+#include "../../c-client/mail.h" /* for MAILSTREAM and friends */
+#include "../../c-client/osdep.h"
+#include "../../c-client/rfc822.h" /* for soutr_t and such */
+#include "../../c-client/misc.h" /* for cpystr proto */
+#include "../../c-client/utf8.h" /* for CHARSET and such*/
+#include "../../c-client/imap4r1.h"
+
+#include "../../pith/osdep/color.h"
+#include "../../pith/state.h"
+
+#include "termin.gen.h"
+#include "termout.gen.h"
+#include "chnge_pw.h"
+
+/*----------------------------------------------------------------------
+ Call the system to change the passwd
+
+It would be nice to talk to the passwd program via a pipe or ptty so the
+user interface could be consistent, but we can't count on the the prompts
+and responses from the passwd program to be regular so we just let the user
+type at the passwd program with some screen space, hope he doesn't scroll
+off the top and repaint when he's done.
+ ----*/
+void
+change_passwd(void)
+{
+#ifdef PASSWD_PROG
+ char cmd_buf[100];
+
+ ClearLines(1, ps_global->ttyo->screen_rows - 1);
+
+ MoveCursor(5, 0);
+ fflush(stdout);
+
+ PineRaw(0);
+ strncpy(cmd_buf, PASSWD_PROG, sizeof(cmd_buf));
+ cmd_buf[sizeof(cmd_buf)-1] = '\0';
+ system(cmd_buf);
+ sleep(3);
+ PineRaw(1);
+#endif /* PASSWD_PROG */
+}
+
+
diff --git a/alpine/osdep/chnge_pw.h b/alpine/osdep/chnge_pw.h
new file mode 100644
index 00000000..ce3463bc
--- /dev/null
+++ b/alpine/osdep/chnge_pw.h
@@ -0,0 +1,25 @@
+/*
+ * $Id: chnge_pw.h 769 2007-10-24 00:15:40Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_CHNGE_PW_INCLUDED
+#define PINE_OSDEP_CHNGE_PW_INCLUDED
+
+
+/* exported prototypes */
+void change_passwd(void);
+
+
+#endif /* PINE_OSDEP_CHNGE_PW_INCLUDED */
diff --git a/alpine/osdep/debuging.c b/alpine/osdep/debuging.c
new file mode 100644
index 00000000..0310f5b5
--- /dev/null
+++ b/alpine/osdep/debuging.c
@@ -0,0 +1,604 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: debuging.c 900 2008-01-05 01:13:26Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2008 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+#include <system.h> /* os-dep defs/includes */
+#include <general.h> /* generally useful definitions */
+
+#include "../../c-client/mail.h" /* for MAILSTREAM and friends */
+#include "../../c-client/osdep.h"
+#include "../../c-client/rfc822.h" /* for soutr_t and such */
+#include "../../c-client/misc.h" /* for cpystr proto */
+#include "../../c-client/utf8.h" /* for CHARSET and such*/
+#include "../../c-client/imap4r1.h"
+
+#include "../../pith/osdep/canaccess.h"
+
+#include "../../pith/debug.h"
+#include "../../pith/osdep/debugtime.h"
+#include "../../pith/osdep/color.h"
+#include "../../pith/osdep/bldpath.h"
+#include "../../pith/osdep/rename.h"
+#include "../../pith/osdep/filesize.h"
+#include "../../pith/init.h"
+#include "../../pith/status.h"
+#include "../../pith/sort.h"
+#include "../../pith/state.h"
+#include "../../pith/msgno.h"
+#include "../../pith/conf.h"
+#include "../../pith/flag.h"
+#include "../../pith/foldertype.h"
+#include "../../pith/folder.h"
+#include "../../pith/charconv/utf8.h"
+#include "../../pith/charconv/filesys.h"
+#include "../help.h"
+
+#include "debuging.h"
+
+
+#ifdef DEBUG
+
+/*
+ * globally visible
+ */
+FILE *debugfile = NULL;
+
+
+/*----------------------------------------------------------------------
+ Initialize debugging - open the debug log file
+
+ Args: none
+
+ Result: opens the debug logfile for dprints
+
+ Opens the file "~/.pine-debug1. Also maintains .pine-debug[2-4]
+ by renaming them each time so the last 4 sessions are saved.
+ ----*/
+void
+init_debug(void)
+{
+ char nbuf[5];
+ char newfname[MAXPATH+1], filename[MAXPATH+1], *dfile = NULL;
+ int i, fd;
+
+ if(!(debug || ps_global->debug_imap || ps_global->debug_tcp))
+ return;
+
+ for(i = ps_global->debug_nfiles - 1; i > 0; i--){
+ build_path(filename, ps_global->home_dir, DEBUGFILE, sizeof(filename));
+ strncpy(newfname, filename, sizeof(newfname)-1);
+ newfname[sizeof(newfname)-1] = '\0';
+ snprintf(nbuf, sizeof(nbuf), "%d", i);
+ strncat(filename, nbuf, sizeof(filename)-1-strlen(filename));
+ snprintf(nbuf, sizeof(nbuf), "%d", i+1);
+ strncat(newfname, nbuf, sizeof(newfname)-1-strlen(newfname));
+ (void)rename_file(filename, newfname);
+ }
+
+ build_path(filename, ps_global->home_dir, DEBUGFILE, sizeof(filename)-1);
+ strncat(filename, "1", sizeof(filename)-1-strlen(filename));
+ filename[sizeof(filename)-1] = '\0';
+
+ debugfile = NULL;
+ dfile = filename;
+ /*
+ * We were doing our_open so _WINDOWS would open it in widechar mode, but
+ * that means we have to print in widechar mode. For now just do open, since
+ * we it's a debug file and still readable. The alternative is copying all
+ * debug text to a widechar buffer, which would be a drag.
+ */
+ if((fd = open(filename, O_TRUNC|O_RDWR|O_CREAT, 0600)) >= 0)
+ debugfile = fdopen(fd, "w+");
+
+ if(debugfile != NULL){
+ char rev[128];
+ time_t now = time((time_t *)0);
+ if(ps_global->debug_flush)
+ setvbuf(debugfile, (char *)NULL, _IOLBF, BUFSIZ);
+
+ if(ps_global->debug_nfiles == 0){
+ /*
+ * If no debug files are asked for, make filename a tempfile
+ * to be used for a record should pine later crash...
+ */
+ if(debug < 9 && !ps_global->debug_flush && ps_global->debug_imap<4){
+ our_unlink(filename);
+ dfile = NULL;
+ }
+ }
+
+ dprint((0, "Debug output of the Alpine program (debug=%d debug_imap=%d). Version %s (%s %s)\n%s\n",
+ debug, ps_global->debug_imap,
+ ALPINE_VERSION,
+ SYSTYPE ? SYSTYPE : "?",
+ get_alpine_revision_string(rev, sizeof(rev)),
+ ctime(&now)));
+
+ dprint((0, "Starting after the reading_pinerc calls, the data in this file should\nbe encoded as UTF-8. Before that it will be in the user's native charset.\n"));
+ if(dfile && (debug > DEFAULT_DEBUG ||
+ ps_global->debug_imap > 0 ||
+ ps_global->debug_tcp > 0)){
+ snprintf(newfname, sizeof(newfname), "Debug file: %s (level=%d imap=%d)", dfile,
+ debug, ps_global->debug_imap);
+ init_error(ps_global, SM_ORDER, 3, 5, newfname);
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------
+ Try to save the debug file if we crash in a controlled way
+
+ Args: dfile: pointer to open debug file
+
+ Result: tries to move the appropriate .pine-debugx file to .pine-crash
+
+ Looks through the four .pine-debug files hunting for the one that is
+ associated with this pine, and then renames it.
+ ----*/
+void
+save_debug_on_crash(FILE *dfile, int (*keystrokes) (int *, char *, size_t))
+{
+ char nbuf[5], crashfile[MAXPATH+1], filename[MAXPATH+1];
+ int i;
+ struct stat dbuf, tbuf;
+ time_t now = time((time_t *)0);
+
+ if(!(dfile && fstat(fileno(dfile), &dbuf) == 0))
+ return;
+
+ fprintf(dfile, "save_debug_on_crash: Version %s: debug level %d",
+ ALPINE_VERSION, debug);
+ fprintf(dfile, "\n : %s\n", ctime(&now));
+
+ build_path(crashfile, ps_global->home_dir, ".pine-crash",sizeof(crashfile));
+
+ fprintf(dfile, "Attempting to save debug file to %s\n\n", crashfile);
+ fprintf(stderr,
+ "\n\n Attempting to save debug file to %s\n\n", crashfile);
+
+ /* Blat out last n keystrokes */
+ if(keystrokes){
+ int cval;
+ char cstr[256];
+
+ fputs("========== Latest Keystrokes =========================\n", dfile);
+
+ while((*keystrokes)(&cval, cstr, sizeof(cstr)) != -1){
+ fprintf(dfile, "\t%s\t(0x%4.4x)\n", cstr, cval);
+ }
+ }
+
+ fputs("========== Latest Keystrokes End =====================\n\n", dfile);
+
+#ifdef DEBUGJOURNAL
+ fputs("========== Append DebugJournal =======================\n", dfile);
+#else /* DEBUGJOURNAL */
+ fputs("========== Append Journal =======================\n", dfile);
+#endif /* DEBUGJOURNAL */
+ debugjournal_to_file(dfile);
+#ifdef DEBUGJOURNAL
+ fputs("========== Append DebugJournal End ===================\n", dfile);
+#else /* DEBUGJOURNAL */
+ fputs("========== Append Journal End ===================\n", dfile);
+#endif /* DEBUGJOURNAL */
+
+ /* look for existing debug file */
+ for(i = 1; i <= ps_global->debug_nfiles; i++){
+ build_path(filename, ps_global->home_dir, DEBUGFILE, sizeof(filename));
+ snprintf(nbuf, sizeof(nbuf), "%d", i);
+ strncat(filename, nbuf, sizeof(filename)-1-strlen(filename));
+ if(our_stat(filename, &tbuf) != 0)
+ continue;
+
+ /* This must be the current debug file */
+ if(tbuf.st_dev == dbuf.st_dev && tbuf.st_ino == dbuf.st_ino){
+ rename_file(filename, crashfile);
+ break;
+ }
+ }
+
+ /* if current debug file name not found, write it by hand */
+ if(i > ps_global->debug_nfiles){
+ FILE *cfp;
+ char buf[1025];
+
+ /*
+ * Copy the debug temp file into the
+ */
+ if((cfp = our_fopen(crashfile, "wb")) != NULL){
+ buf[sizeof(buf)-1] = '\0';
+ fseek(dfile, 0L, 0);
+ while(fgets(buf, sizeof(buf)-1, dfile) && fputs(buf, cfp) != EOF)
+ ;
+
+ fclose(cfp);
+ }
+ }
+
+ fclose(dfile);
+}
+
+
+/*
+ * functions required by pith library
+ */
+#define CHECK_EVERY_N_TIMES 100
+#define MAX_DEBUG_FILE_SIZE 200000L
+/*
+ * This is just to catch runaway Pines that are looping spewing out
+ * debugging (and filling up a file system). The stop doesn't have to be
+ * at all precise, just soon enough to hopefully prevent filling the
+ * file system. If the debugging level is high (9 for now), then we're
+ * presumably looking for some problem, so don't truncate.
+ */
+int
+do_debug(FILE *debug_fp)
+{
+ static int counter = CHECK_EVERY_N_TIMES;
+ static int ok = 1;
+ long filesize;
+
+ if(!debugfile)
+ return(0);
+
+ if(debug <= DEFAULT_DEBUG
+ && !ps_global->debug_flush
+ && !ps_global->debug_tcp
+ && !ps_global->debug_timestamp
+ && !ps_global->debug_imap
+ && ok
+ && --counter <= 0){
+ if((filesize = fp_file_size(debug_fp)) != -1L)
+ ok = (unsigned long)filesize < (unsigned long)MAX_DEBUG_FILE_SIZE;
+
+ counter = CHECK_EVERY_N_TIMES;
+ if(!ok){
+ fprintf(debug_fp, "\n\n --- No more debugging ---\n");
+ fprintf(debug_fp,
+ " (debug file growing too large - over %ld bytes)\n\n",
+ MAX_DEBUG_FILE_SIZE);
+ fflush(debug_fp);
+ }
+ }
+
+ if(ok && ps_global->debug_timestamp)
+ fprintf(debug_fp, "\n%s\n", debug_time(0, ps_global->debug_timestamp));
+
+ return(ok);
+}
+
+void
+output_debug_msg(int dlevel, char *fmt, ...)
+{
+ va_list args;
+
+ if(debugfile && debug >= dlevel && do_debug(debugfile)){
+ int l;
+
+ va_start(args, fmt);
+ vfprintf(debugfile, fmt, args);
+ va_end(args);
+
+ if((l = strlen(fmt)) > 2 && fmt[l-1] != '\n')
+ fputc('\n', debugfile);
+
+ if(ps_global->debug_flush)
+ fflush(debugfile);
+ }
+
+ if(panicking())
+ return;
+
+#ifdef DEBUGJOURNAL
+
+ if(dlevel <= 9 || dlevel <= debug){
+ /*
+ * Make this static in order to move it off of
+ * the stack. We were getting "random" crashes
+ * on some systems when this size interacted with
+ * pthread stack size somehow. Taking it off of
+ * the stack ought to fix that without us having to
+ * understand how it all works.
+ */
+ static char b[64000];
+
+ va_start(args, fmt);
+ vsnprintf(b, sizeof(b), fmt, args);
+ va_end(args);
+
+ b[sizeof(b)-1] = '\0';
+ add_review_message(b, dlevel);
+ }
+
+#endif /* DEBUGJOURNAL */
+
+}
+
+
+/*----------------------------------------------------------------------
+ Dump the whole config enchilada using the given function
+
+ Args: ps -- pine struct containing vars to dump
+ pc -- function to use to write the config data
+ brief -- brief dump, only dump user_vals
+ Result: command line, global, user var's written with given function
+
+ ----*/
+void
+dump_configuration(int brief)
+{
+ gf_io_t pc;
+
+ if(!do_debug(debugfile))
+ return;
+
+ gf_set_writec(&pc, debugfile, 0L, FileStar, 0);
+
+ dump_config(ps_global, pc, brief);
+}
+
+
+void
+dump_config(struct pine *ps, gf_io_t pc, int brief)
+{
+ int i;
+ char quotes[3], tmp[MAILTMPLEN];
+ register struct variable *vars;
+ FEATURE_S *feat;
+
+ quotes[0] = '"'; quotes[1] = '"'; quotes[2] = '\0';
+
+ for(i = (brief ? 2 : 0); i < (brief ? 4 : 6); i++){
+ snprintf(tmp, sizeof(tmp), "======= %.20s_val options set",
+ (i == 0) ? "Current" :
+ (i == 1) ? "Command_line" :
+ (i == 2) ? "User" :
+ (i == 3) ? "PostloadUser" :
+ (i == 4) ? "Global"
+ : "Fixed");
+ gf_puts(tmp, pc);
+ if(i > 1){
+ snprintf(tmp, sizeof(tmp), " (%.100s)",
+ (i == 2) ? ((ps->prc) ? ps->prc->name : ".pinerc") :
+ (i == 3) ? ((ps->post_prc) ? ps->post_prc->name : "postload") :
+ (i == 4) ? ((ps->pconf) ? ps->pconf->name
+ : SYSTEM_PINERC) :
+#if defined(DOS) || defined(OS2)
+ "NO FIXED"
+#else
+ ((can_access(SYSTEM_PINERC_FIXED, ACCESS_EXISTS) == 0)
+ ? SYSTEM_PINERC_FIXED : "NO pine.conf.fixed")
+#endif
+ );
+ gf_puts(tmp, pc);
+ }
+
+ gf_puts(" =======\n", pc);
+ for(vars = ps->vars; vars->name; vars++){
+ if(vars->is_list){
+ char **t;
+ t = (i == 0) ? vars->current_val.l :
+ (i == 1) ? vars->cmdline_val.l :
+ (i == 2) ? vars->main_user_val.l :
+ (i == 3) ? vars->post_user_val.l :
+ (i == 4) ? vars->global_val.l
+ : vars->fixed_val.l;
+ if(t && *t){
+ snprintf(tmp, sizeof(tmp), " %20.20s : %.*s\n", vars->name,
+ sizeof(tmp)-26, **t ? *t : quotes);
+ gf_puts(tmp, pc);
+ while(++t && *t){
+ snprintf(tmp, sizeof(tmp)," %20.20s : %.*s\n","",
+ sizeof(tmp)-26, **t ? *t : quotes);
+ gf_puts(tmp, pc);
+ }
+ }
+ }
+ else{
+ char *t;
+ t = (i == 0) ? vars->current_val.p :
+ (i == 1) ? vars->cmdline_val.p :
+ (i == 2) ? vars->main_user_val.p :
+ (i == 3) ? vars->post_user_val.p :
+ (i == 4) ? vars->global_val.p
+ : vars->fixed_val.p;
+ if(t){
+ snprintf(tmp, sizeof(tmp), " %20.20s : %.*s\n", vars->name,
+ sizeof(tmp)-26, *t ? t : quotes);
+ gf_puts(tmp, pc);
+ }
+ }
+ }
+ }
+
+ if(!brief){
+ gf_puts("========== Feature settings ==========\n", pc);
+ for(i = 0; (feat = feature_list(i)); i++)
+ if(feat->id != F_OLD_GROWTH){
+ snprintf(tmp, sizeof(tmp),
+ " %.50s%.100s\n", F_ON(feat->id, ps) ? " " : "no-",
+ feat->name);
+ gf_puts(tmp, pc);
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------
+ Dump interesting variables from the given pine struct
+
+ Args: ps -- pine struct to dump
+ pc -- function to use to write the config data
+
+ Result: various important pine struct data written
+
+ ----*/
+void
+dump_pine_struct(struct pine *ps, gf_io_t pc)
+{
+ char *p;
+ extern char term_name[];
+ int i;
+ MAILSTREAM *m;
+ MSGNO_S *msgmap;
+
+ gf_puts("========== struct pine * ==========\n", pc);
+ if(!ps){
+ gf_puts("!No struct!\n", pc);
+ return;
+ }
+
+ gf_puts("ui:\tlogin = ", pc);
+ gf_puts((ps->ui.login) ? ps->ui.login : "NULL", pc);
+ gf_puts(", full = ", pc);
+ gf_puts((ps->ui.fullname) ? ps->ui.fullname : "NULL", pc);
+ gf_puts("\n\thome = ", pc);
+ gf_puts((ps->ui.homedir) ? ps->ui.homedir : "NULL", pc);
+
+ gf_puts("\nhome_dir=\t", pc);
+ gf_puts(ps->home_dir ? ps->home_dir : "NULL", pc);
+ gf_puts("\nhostname=\t", pc);
+ gf_puts(ps->hostname ? ps->hostname : "NULL", pc);
+ gf_puts("\nlocaldom=\t", pc);
+ gf_puts(ps->localdomain ? ps->localdomain : "NULL", pc);
+ gf_puts("\nuserdom=\t", pc);
+ gf_puts(ps->userdomain ? ps->userdomain : "NULL", pc);
+ gf_puts("\nmaildom=\t", pc);
+ gf_puts(ps->maildomain ? ps->maildomain : "NULL", pc);
+
+ gf_puts("\ncur_cntxt=\t", pc);
+ gf_puts((ps->context_current && ps->context_current->context)
+ ? ps->context_current->context : "None", pc);
+ gf_puts("\ncur_fldr=\t", pc);
+ gf_puts(ps->cur_folder, pc);
+
+ gf_puts("\nnstream=\t", pc);
+ gf_puts(long2string((long) ps->s_pool.nstream), pc);
+
+ for(i = 0; i < ps->s_pool.nstream; i++){
+ m = ps->s_pool.streams[i];
+ gf_puts("\nstream slot ", pc);
+ gf_puts(long2string((long) i), pc);
+ if(!m){
+ gf_puts(" empty", pc);
+ continue;
+ }
+
+ if(ps->mail_stream == m)
+ gf_puts("\nThis is the current mailstream", pc);
+ if(sp_flagged(m, SP_INBOX))
+ gf_puts("\nThis is the inbox stream", pc);
+
+ gf_puts("\nactual mbox=\t", pc);
+ gf_puts(m->mailbox ? m->mailbox : "no mailbox!", pc);
+
+ gf_puts("\nflags=", pc);
+ gf_puts(long2string((long) sp_flags(m)), pc);
+ gf_puts("\nnew_mail_count=", pc);
+ gf_puts(long2string((long) sp_new_mail_count(m)), pc);
+ gf_puts("\nmail_since_cmd=", pc);
+ gf_puts(long2string((long) sp_mail_since_cmd(m)), pc);
+ gf_puts("\nmail_box_changed=", pc);
+ gf_puts(long2string((long) sp_mail_box_changed(m)), pc);
+ gf_puts("\nunsorted_newmail=", pc);
+ gf_puts(long2string((long) sp_unsorted_newmail(m)), pc);
+ gf_puts("\nneed_to_rethread=", pc);
+ gf_puts(long2string((long) sp_need_to_rethread(m)), pc);
+ gf_puts("\nviewing_a_thread=", pc);
+ gf_puts(long2string((long) sp_viewing_a_thread(m)), pc);
+ gf_puts("\ndead_stream=", pc);
+ gf_puts(long2string((long) sp_dead_stream(m)), pc);
+ gf_puts("\nnoticed_dead_stream=", pc);
+ gf_puts(long2string((long) sp_noticed_dead_stream(m)), pc);
+ gf_puts("\nio_error_on_stream=", pc);
+ gf_puts(long2string((long) sp_io_error_on_stream(m)), pc);
+
+ msgmap = sp_msgmap(m);
+ if(msgmap){
+ gf_puts("\nmsgmap: tot=", pc);
+ gf_puts(long2string(mn_get_total(msgmap)), pc);
+ gf_puts(", cur=", pc);
+ gf_puts(long2string(mn_get_cur(msgmap)), pc);
+ gf_puts(", del=", pc);
+ gf_puts(long2string(count_flagged(m, F_DEL)),pc);
+ gf_puts(", hid=", pc);
+ gf_puts(long2string(any_lflagged(msgmap, MN_HIDE)), pc);
+ gf_puts(", exld=", pc);
+ gf_puts(long2string(any_lflagged(msgmap, MN_EXLD)), pc);
+ gf_puts(", slct=", pc);
+ gf_puts(long2string(any_lflagged(msgmap, MN_SLCT)), pc);
+ gf_puts(", chid=", pc);
+ gf_puts(long2string(any_lflagged(msgmap, MN_CHID)), pc);
+ gf_puts(", coll=", pc);
+ gf_puts(long2string(any_lflagged(msgmap, MN_COLL)), pc);
+ gf_puts(", usor=", pc);
+ gf_puts(long2string(any_lflagged(msgmap, MN_USOR)), pc);
+ gf_puts(", stmp=", pc);
+ gf_puts(long2string(any_lflagged(msgmap, MN_STMP)), pc);
+ gf_puts(", sort=", pc);
+ if(mn_get_revsort(msgmap))
+ gf_puts("rev-", pc);
+
+ gf_puts(sort_name(mn_get_sort(msgmap)), pc);
+ }
+ else
+ gf_puts("\nNo msgmap", pc);
+ }
+
+
+ gf_puts("\nterm ", pc);
+#if !defined(DOS) && !defined(OS2)
+ gf_puts("type=", pc);
+ gf_puts(term_name, pc);
+ gf_puts(", ttyname=", pc);
+ gf_puts((p = (char *)ttyname(0)) ? p : "NONE", pc);
+#endif
+ gf_puts(", size=", pc);
+ gf_puts(int2string(ps->ttyo->screen_rows), pc);
+ gf_puts("x", pc);
+ gf_puts(int2string(ps->ttyo->screen_cols), pc);
+ gf_puts(", speed=", pc);
+ gf_puts((ps->low_speed) ? "slow" : "normal", pc);
+ gf_puts("\n", pc);
+}
+
+
+void
+dump_contexts(void)
+{
+ int i = 0;
+ CONTEXT_S *c = ps_global->context_list;
+
+ if(!(debugfile && debug > 7 && do_debug(debugfile)))
+ return;
+
+ while(debugfile && c != NULL){
+ fprintf(debugfile, "\n***** context %s\n", c->context);
+ if(c->label)
+ fprintf(debugfile,"LABEL: %s\n", c->label);
+
+ if(c->comment)
+ fprintf(debugfile,"COMMENT: %s\n", c->comment);
+
+ for(i = 0; i < folder_total(FOLDERS(c)); i++)
+ fprintf(debugfile, " %d) %s\n", i + 1, folder_entry(i,FOLDERS(c))->name);
+
+ c = c->next;
+ }
+}
+
+#endif /* DEBUG */
diff --git a/alpine/osdep/debuging.h b/alpine/osdep/debuging.h
new file mode 100644
index 00000000..aee9d721
--- /dev/null
+++ b/alpine/osdep/debuging.h
@@ -0,0 +1,30 @@
+/*
+ * $Id: debuging.h 761 2007-10-23 22:35:18Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_DEBUGING_INCLUDED
+#define PINE_OSDEP_DEBUGING_INCLUDED
+
+/* stream to stuff debuging output */
+extern FILE *debugfile;
+
+/*
+ * Exported Prototypes
+ */
+#ifdef DEBUG
+void init_debug(void);
+void save_debug_on_crash(FILE *, int (*)(int *, char *, size_t));
+#endif
+
+#endif /* PINE_OSDEP_DEBUGING_INCLUDED */
diff --git a/alpine/osdep/diskquot b/alpine/osdep/diskquot
new file mode 100644
index 00000000..4ff6b261
--- /dev/null
+++ b/alpine/osdep/diskquot
@@ -0,0 +1,78 @@
+#if defined(USE_QUOTAS)
+
+#include <sys/param.h>
+#include <sys/quota.h>
+
+/*----------------------------------------------------------------------
+ Return space left in disk quota on file system which given path is in.
+
+ Args: path - Path name of file or directory on file system of concern
+ over - pointer to flag that is set if the user is over quota
+
+ Returns: If *over = 0, the number of bytes free in disk quota as per
+ the soft limit.
+ If *over = 1, the number of bytes *over* quota.
+ -1 is returned on an error looking up quota
+ 0 is returned if there is no quota
+
+BUG: If there's more than 2.1Gb free this function will break
+ ----*/
+long
+disk_quota(path, over)
+ char *path;
+ int *over;
+{
+ static int no_quota = 0;
+ struct stat statx;
+ struct dqblk quotax;
+ long q;
+
+ if(no_quota)
+ return(0L); /* If no quota the first time, then none the second,
+ Also Ultrix seems to give the wrong answer the second
+ time */
+
+ dprint(5, (debugfile, "quota_check path: %s\n", path ? path : "?"));
+ if(stat(path, &statx) < 0) {
+ return(-1L);
+ }
+
+ *over = 0;
+ errno = 0;
+
+ dprint(7, (debugfile, "Quota check: UID:%d stat: %d %x\n",
+ getuid(), statx.st_dev, statx.st_dev));
+ memset((void *)&quotax, 0, sizeof(struct dqblk));
+ if(quota(Q_GETDLIM, getuid(), statx.st_dev, &quotax) < 0) {
+ dprint(5, (debugfile, "Quota failed : %s\n",
+ error_description(errno)));
+ if(errno == ESRCH){
+ no_quota = 1;
+ return(0L); /* No limit */
+ } else {
+ return(-1L); /* Some thing went wrong */
+ }
+ }
+
+ dprint(5,(debugfile,"Quota: bsoftlimit:%d bhardlimit:%d curblock:%d\n",
+ quotax.dqb_bsoftlimit, quotax.dqb_bhardlimit, quotax.dqb_curblocks));
+
+ /* Some confusion on the type of bsoftlimit. The include file says
+ unsigned, but -1 seems to indicate no quota */
+ if(quotax.dqb_bsoftlimit == 0 || (long)quotax.dqb_bsoftlimit == -1) {
+ no_quota = 1;
+ return(0L);
+ }
+
+ q = (quotax.dqb_bsoftlimit - quotax.dqb_curblocks) * 1024;
+
+ if(q < 0) {
+ q = -q;
+ *over = 1;
+ }
+ dprint(5, (debugfile, "disk_quota returning :%d, over:%d\n", q, *over));
+ return(q);
+}
+#endif /* USE_QUOTAS */
+
+
diff --git a/alpine/osdep/diskquot.a32 b/alpine/osdep/diskquot.a32
new file mode 100644
index 00000000..c4695764
--- /dev/null
+++ b/alpine/osdep/diskquot.a32
@@ -0,0 +1,8 @@
+#if defined(USE_QUOTAS)
+
+#include <jfs/quota.h>
+
+include(sunquota)
+#endif /* USE_QUOTAS */
+
+
diff --git a/alpine/osdep/diskquot.a41 b/alpine/osdep/diskquot.a41
new file mode 100644
index 00000000..564c4201
--- /dev/null
+++ b/alpine/osdep/diskquot.a41
@@ -0,0 +1,6 @@
+#if defined(USE_QUOTAS)
+#include <jfs/quota.h>
+
+include(sunquota)
+#endif /* USE_QUOTAS */
+
diff --git a/alpine/osdep/diskquot.hpp b/alpine/osdep/diskquot.hpp
new file mode 100644
index 00000000..1b328cd6
--- /dev/null
+++ b/alpine/osdep/diskquot.hpp
@@ -0,0 +1,9 @@
+#if defined(USE_QUOTAS)
+
+#include <sys/param.h>
+#include <sys/quota.h>
+
+include(sunquota)
+#endif /* USE_QUOTAS */
+
+
diff --git a/alpine/osdep/diskquot.non.c b/alpine/osdep/diskquot.non.c
new file mode 100644
index 00000000..17465f63
--- /dev/null
+++ b/alpine/osdep/diskquot.non.c
@@ -0,0 +1,46 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: diskquot.non.c 761 2007-10-23 22:35:18Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#include <system.h>
+
+#ifdef USE_QUOTAS
+
+/*----------------------------------------------------------------------
+ This system doesn't have disk quotas.
+ Return space left in disk quota on file system which given path is in.
+
+ Args: path - Path name of file or directory on file system of concern
+ over - pointer to flag that is set if the user is over quota
+
+ Returns: If *over = 0, the number of bytes free in disk quota as per
+ the soft limit.
+ If *over = 1, the number of bytes *over* quota.
+ -1 is returned on an error looking up quota
+ 0 is returned if there is no quota
+
+BUG: If there's more than 2.1Gb free this function will break
+ ----*/
+long
+disk_quota(path, over)
+ char *path;
+ int *over;
+{
+ return(0L);
+}
+#endif /* USE_QUOTAS */
+
+
diff --git a/alpine/osdep/diskquot.ptx b/alpine/osdep/diskquot.ptx
new file mode 100644
index 00000000..b636db08
--- /dev/null
+++ b/alpine/osdep/diskquot.ptx
@@ -0,0 +1,9 @@
+#if defined(USE_QUOTAS)
+
+#include <sys/ufsquota.h>
+#define MTABNAME "/etc/mnttab"
+
+include(sunquota)
+#endif /* USE_QUOTAS */
+
+
diff --git a/alpine/osdep/diskquot.sgi b/alpine/osdep/diskquot.sgi
new file mode 100644
index 00000000..3100d06c
--- /dev/null
+++ b/alpine/osdep/diskquot.sgi
@@ -0,0 +1,8 @@
+#if defined(USE_QUOTAS)
+
+#include <sys/quota.h>
+
+include(sunquota)
+#endif /* USE_QUOTAS */
+
+
diff --git a/alpine/osdep/diskquot.so5 b/alpine/osdep/diskquot.so5
new file mode 100644
index 00000000..ffd4ca93
--- /dev/null
+++ b/alpine/osdep/diskquot.so5
@@ -0,0 +1,9 @@
+#if defined(USE_QUOTAS)
+
+#include <sys/fs/ufs_quota.h>
+#define MTABNAME "/etc/mnttab"
+
+include(solquota)
+#endif /* USE_QUOTAS */
+
+
diff --git a/alpine/osdep/diskquot.sun b/alpine/osdep/diskquot.sun
new file mode 100644
index 00000000..e8cb0506
--- /dev/null
+++ b/alpine/osdep/diskquot.sun
@@ -0,0 +1,8 @@
+#if defined(USE_QUOTAS)
+
+#include <ufs/quota.h>
+
+include(sunquota)
+#endif /* USE_QUOTAS */
+
+
diff --git a/alpine/osdep/diskquot.sv4 b/alpine/osdep/diskquot.sv4
new file mode 100644
index 00000000..dc330a30
--- /dev/null
+++ b/alpine/osdep/diskquot.sv4
@@ -0,0 +1,9 @@
+#if defined(USE_QUOTAS)
+
+#include <sys/fs/ufs_quota.h>
+#define MTABNAME "/etc/mnttab"
+
+include(sunquota)
+#endif /* USE_QUOTAS */
+
+
diff --git a/alpine/osdep/execview.c b/alpine/osdep/execview.c
new file mode 100644
index 00000000..da7310df
--- /dev/null
+++ b/alpine/osdep/execview.c
@@ -0,0 +1,555 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: execview.c 942 2008-03-04 18:21:33Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2008 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#include <system.h>
+#include <general.h>
+
+#include "../../c-client/mail.h" /* for MAILSTREAM and friends */
+#include "../../c-client/osdep.h"
+#include "../../c-client/rfc822.h" /* for soutr_t and such */
+#include "../../c-client/misc.h" /* for cpystr proto */
+#include "../../c-client/utf8.h" /* for CHARSET and such*/
+#include "../../c-client/imap4r1.h"
+
+#include "../../pith/debug.h"
+
+#include "../../pith/osdep/temp_nam.h"
+#include "../../pith/osdep/color.h"
+#include "../../pith/osdep/mimedisp.h"
+
+#include "../../pith/charconv/utf8.h"
+#include "../../pith/charconv/filesys.h"
+
+#include "../pith/mailcap.h"
+
+#include "../status.h"
+#include "../radio.h"
+#include "../signal.h"
+#include "../../pico/estruct.h"
+#include "../../pico/pico.h"
+#include "../mailview.h"
+#include "termin.gen.h"
+
+#ifdef _WINDOWS
+#include "../../pico/osdep/mswin.h"
+#endif
+
+/* Useful structures */
+#if OSX_TARGET
+typedef struct _execview_event_data_s {
+ int done;
+ ProcessSerialNumber pid;
+ int set_pid;
+} EXEC_EVENT_DATA_S;
+#endif
+
+
+/* internal prototypes */
+#if OSX_TARGET
+pascal OSStatus osx_launch_app_callback(EventHandlerCallRef,
+ EventRef, void *);
+int install_app_launch_cb(void *);
+void osx_launch_special_handling(MCAP_CMD_S *, char *);
+#endif
+
+
+
+/* ----------------------------------------------------------------------
+ Execute the given mailcap command
+
+ Args: cmd -- the command to execute
+ image_file -- the file the data is in
+ needsterminal -- does this command want to take over the terminal?
+ ----*/
+void
+exec_mailcap_cmd(MCAP_CMD_S *mc_cmd, char *image_file, int needsterminal)
+{
+#ifdef _WINDOWS
+ STARTUPINFO start_info;
+ PROCESS_INFORMATION proc_info;
+ WINHAND childProcess;
+ int success = 0;
+ char *cmd;
+ LPTSTR image_file_lpt = NULL;
+ LPTSTR cmd_lpt = NULL;
+
+ /* no special handling yet, but could be used to replace '*' hack */
+ if(mc_cmd)
+ cmd = mc_cmd->command;
+ else
+ return;
+
+ dprint((9, "run_viewer: command=%s\n", cmd ? cmd : "?")) ;
+
+ if(image_file)
+ image_file_lpt = utf8_to_lptstr(image_file);
+
+ /* Set to READONLY so the viewer can't try to edit it and keep it around */
+ if(image_file_lpt)
+ SetFileAttributes(image_file_lpt, FILE_ATTRIBUTE_READONLY);
+
+ if(*cmd == '*' || (*cmd == '\"' && *(cmd+1) == '*')){
+ /*
+ * It has been asked that there be the ability to do an
+ * "Open With..." on attachments like you can from the
+ * Windows file browser. After looking into this, it
+ * seems that the only way to do this would be through
+ * an undocumented hack. Here, we would pass "openas" as
+ * the verb to mswin_shell_exec (also some changes in
+ * mswin_shell_exec). Since this is the delicate world
+ * of attachment handling, it seems right not to rely on
+ * a hack. The interface wouldn't be too clean anyways,
+ * as we would have to download the attachment only to
+ * display the "Open With..." dialog. Go figure, some
+ * things Microsoft just wants to keep to themselves.
+ */
+
+ /*
+ * 2/1/2007. No idea when the above comment was written, but it is
+ * documented now at least. The below two urls describe the "openas" verb:
+ *
+ * http://blogs.msdn.com/oldnewthing/archive/2004/11/26/270710.aspx
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
+ * shellcc/platform/shell/programmersguide/shell_basics/
+ * shell_basics_extending/context.asp
+ */
+ success = mswin_shell_exec(cmd, &childProcess) == 0;
+ }
+ else{
+ memset(&proc_info, 0, sizeof(proc_info));
+ memset(&start_info, 0, sizeof(start_info));
+ start_info.dwFlags = STARTF_FORCEONFEEDBACK;
+ start_info.wShowWindow = SW_SHOWNORMAL;
+
+ if(cmd)
+ cmd_lpt = utf8_to_lptstr(cmd);
+
+ if(CreateProcess(NULL, cmd_lpt, NULL, NULL, FALSE,
+ CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
+ NULL, NULL, &start_info, &proc_info) == TRUE){
+ q_status_message(SM_ORDER, 0, 4, "VIEWER command completed");
+ dprint ((3, "CreatProcess(%s) Success.\n",
+ cmd ? cmd : "?"));
+ childProcess = proc_info.hProcess;
+ success = 1;
+ }
+
+ if(cmd_lpt)
+ fs_give((void **) &cmd_lpt);
+ }
+
+ if(!success){
+ int rc = (int) GetLastError();
+ if(image_file_lpt)
+ SetFileAttributes(image_file_lpt, FILE_ATTRIBUTE_NORMAL);
+
+ our_unlink(image_file);
+ q_status_message2(SM_ORDER, 3, 4, "\007Can't start viewer. %s%s.",
+ (rc == 2 || rc == 3) ? "Viewer not found: " :
+ (rc == 8) ? "Not enough memory" : "Windows error ",
+ (rc == 2 || rc == 3) ? cmd :
+ (rc == 8) ? "" : int2string(rc));
+ }
+
+ if(image_file_lpt)
+ fs_give((void **) &image_file_lpt);
+
+#elif OSX_TARGET
+
+ char *command = NULL,
+ *result_file = NULL,
+ *p;
+ char **r_file_h;
+ PIPE_S *syspipe;
+ int mode;
+
+ if(!mc_cmd)
+ return;
+ if(mc_cmd->special_handling){
+ char *rhost;
+
+ if(mime_os_specific_access())
+ osx_launch_special_handling(mc_cmd, image_file);
+ else{
+ q_status_message(SM_ORDER, 0, 4, "VIEWER command cancelled");
+ our_unlink(image_file);
+ }
+ }
+ else {
+ char *cmd = mc_cmd->command;
+ size_t l;
+
+ l = 32 + strlen(cmd) + (2*strlen(image_file));
+ p = command = (char *) fs_get((l+1) * sizeof(char));
+ if(!needsterminal) /* put in background if it doesn't need terminal */
+ *p++ = '(';
+
+ snprintf(p, l+1-(p-command), "%s", cmd);
+ p += strlen(p);
+ if(!needsterminal){
+ if(p-command+2 < l+1){
+ *p++ = ')';
+ *p++ = ' ';
+ *p++ = '&';
+ }
+ }
+
+ if(p-command < l+1)
+ *p++ = '\n';
+
+ if(p-command < l+1)
+ *p = '\0';
+
+ dprint((9, "exec_mailcap_cmd: command=%s\n",
+ command ? command : "?"));
+
+ mode = PIPE_RESET;
+ if(needsterminal == 1)
+ r_file_h = NULL;
+ else{
+ mode |= PIPE_WRITE | PIPE_STDERR;
+ result_file = temp_nam(NULL, "pine_cmd");
+ r_file_h = &result_file;
+ }
+
+ if(syspipe = open_system_pipe(command, r_file_h, NULL, mode, 0, pipe_callback, NULL)){
+ close_system_pipe(&syspipe, NULL, pipe_callback);
+ if(needsterminal == 1)
+ q_status_message(SM_ORDER, 0, 4, "VIEWER command completed");
+ else if(needsterminal == 2)
+ display_output_file(result_file, "VIEWER", " command result", 1);
+ else
+ display_output_file(result_file, "VIEWER", " command launched", 1);
+ }
+ else
+ q_status_message1(SM_ORDER, 3, 4, "Cannot spawn command : %s", cmd);
+
+ fs_give((void **)&command);
+ if(result_file)
+ fs_give((void **)&result_file);
+ }
+#else
+ char *command = NULL,
+ *result_file = NULL,
+ *p, *cmd;
+ char **r_file_h;
+ PIPE_S *syspipe;
+ int mode;
+ size_t l;
+
+ /* no os-specific command handling */
+ if(mc_cmd)
+ cmd = mc_cmd->command;
+ else
+ return;
+ l = 32 + strlen(cmd) + 2*strlen(image_file);
+ p = command = (char *)fs_get((l+1) * sizeof(char));
+ if(!needsterminal) /* put in background if it doesn't need terminal */
+ *p++ = '(';
+ snprintf(p, l+1-(p-command), "%s ; rm -f %s", cmd, image_file);
+ command[l] = '\0';
+ p += strlen(p);
+ if(!needsterminal && (p-command)+5 < l){
+ *p++ = ')';
+ *p++ = ' ';
+ *p++ = '&';
+ }
+
+ *p++ = '\n';
+ *p = '\0';
+
+ dprint((9, "exec_mailcap_cmd: command=%s\n",
+ command ? command : "?"));
+
+ mode = PIPE_RESET;
+ if(needsterminal == 1)
+ r_file_h = NULL;
+ else{
+ mode |= PIPE_WRITE | PIPE_STDERR;
+ result_file = temp_nam(NULL, "pine_cmd");
+ r_file_h = &result_file;
+ }
+
+ if((syspipe = open_system_pipe(command, r_file_h, NULL, mode, 0, pipe_callback, NULL)) != NULL){
+ close_system_pipe(&syspipe, NULL, pipe_callback);
+ if(needsterminal == 1)
+ q_status_message(SM_ORDER, 0, 4, "VIEWER command completed");
+ else if(needsterminal == 2)
+ display_output_file(result_file, "VIEWER", " command result", 1);
+ else
+ display_output_file(result_file, "VIEWER", " command launched", 1);
+ }
+ else
+ q_status_message1(SM_ORDER, 3, 4, "Cannot spawn command : %s", cmd);
+
+ fs_give((void **)&command);
+
+ if(result_file)
+ fs_give((void **)&result_file);
+#endif
+}
+
+
+/* ----------------------------------------------------------------------
+ Execute the given mailcap test= cmd
+
+ Args: cmd -- command to execute
+ Returns exit status
+
+ ----*/
+int
+exec_mailcap_test_cmd(char *cmd)
+{
+#ifdef _WINDOWS
+ return((WinExec(cmd, SW_SHOWMINNOACTIVE) < 32) ? 1 : 0);
+#else
+ PIPE_S *syspipe;
+
+ return((syspipe = open_system_pipe(cmd, NULL, NULL, PIPE_SILENT, 0,
+ pipe_callback, NULL))
+ ? close_system_pipe(&syspipe, NULL, pipe_callback) : -1);
+#endif
+}
+
+
+char *
+url_os_specified_browser(char *url)
+{
+#ifdef _WINDOWS
+ return(mswin_reg_default_browser(url));
+#elif OSX_TARGET
+ if(mime_os_specific_access()){
+ return(cpystr("open"));
+ }
+#else
+ /* do nothing here */
+ return(NULL);
+#endif
+}
+
+/*
+ * Return a pretty command, on some OS's we might do something
+ * different than just display the command.
+ *
+ * free_ret - whether or not to free the return value
+ */
+char *
+execview_pretty_command(MCAP_CMD_S *mc_cmd, int *free_ret)
+{
+ char *str;
+ int rv_to_free = 0;
+
+ if(free_ret)
+ *free_ret = rv_to_free;
+
+ if(!mc_cmd)
+ return NULL;
+
+ str = mc_cmd->command;
+
+#ifdef _WINDOWS
+ if(*str == '*' || (*str == '\"' && str[1] == '*')){
+ if(!strncmp(str + ((*str == '\"') ? 2 : 1), "DDE*", 4))
+ str = cpystr("via app already running");
+ else if(!strncmp(str + ((*str == '\"') ? 2 : 1),"ShellEx*",8))
+ str = cpystr("via Explorer defined app");
+ else
+ str = cpystr("via Windows-specific method");
+
+ rv_to_free = 1;
+ }
+#elif OSX_TARGET
+ if(mc_cmd->special_handling){
+ CFStringRef str_ref = NULL, kind_str_ref = NULL;
+ CFURLRef url_ref;
+ char buf[256];
+
+ if((str_ref = CFStringCreateWithCString(NULL, mc_cmd->command,
+ kCFStringEncodingASCII)) == NULL)
+ return "";
+
+ if((url_ref = CFURLCreateWithString(NULL, str_ref, NULL)) == NULL)
+ return "";
+
+ if(LSCopyDisplayNameForURL(url_ref, &kind_str_ref) != noErr)
+ return "";
+
+ if(CFStringGetCString(kind_str_ref, buf, (CFIndex)255,
+ kCFStringEncodingASCII) == false)
+ return "";
+
+ buf[255] = '\0';
+ str = cpystr(buf);
+ rv_to_free = 1;
+ if(kind_str_ref)
+ CFRelease(kind_str_ref);
+ }
+#else
+ /* always pretty */
+#endif
+
+ if(free_ret)
+ *free_ret = rv_to_free;
+
+ return(str);
+}
+
+
+#if OSX_TARGET
+void
+osx_launch_special_handling(MCAP_CMD_S *mc_cmd, char *image_file)
+{
+ CFStringRef str_ref = NULL;
+ CFURLRef url_ref = NULL;
+ LSLaunchFSRefSpec launch_spec;
+ FSRef app_ref, file_ref;
+ static EXEC_EVENT_DATA_S event_data;
+
+ install_app_launch_cb((void *)&event_data);
+ if((str_ref = CFStringCreateWithCString(NULL, mc_cmd->command,
+ kCFStringEncodingASCII)) == NULL)
+ return;
+ if((url_ref = CFURLCreateWithString(NULL, str_ref, NULL)) == NULL)
+ return;
+ if(CFURLGetFSRef(url_ref, &app_ref) == false)
+ return;
+ if(FSPathMakeRef((unsigned char *)image_file,
+ &file_ref, NULL) != noErr)
+ return;
+ launch_spec.appRef = &app_ref;
+ launch_spec.numDocs = 1;
+ launch_spec.itemRefs = &file_ref;
+ launch_spec.passThruParams = NULL;
+ launch_spec.launchFlags = kLSLaunchDontAddToRecents | kLSLaunchNoParams
+ | kLSLaunchAsync | kLSLaunchNewInstance;
+ /* would want to use this if we ever did true event handling */
+ launch_spec.asyncRefCon = 0;
+
+ if(LSOpenFromRefSpec( &launch_spec, NULL) == noErr){
+ /*
+ * Here's the strategy: we want to be able to just launch
+ * the app and then just delete the temp file, but that
+ * doesn't work because the called app needs the temp file
+ * at least until it's finished loading. Being that there's
+ * no way to tell when the app has finished loading, we wait
+ * until the program has exited, which is the safest thing to
+ * do and is what we do for windows. Since we haven't totally
+ * embraced event handling at this point, we must do the waiting
+ * synchronously. We allow for a keystroke to stop waiting, and
+ * just delete the temp file.
+ * Ideally, we would launch the app, and keep running, checking
+ * the events until the process terminates, and then delete the
+ * temp file. In this method, we would delete the temp file
+ * at close time if the app was still running.
+ */
+ int ch;
+ OSStatus rne_rv;
+ EventTargetRef target;
+ EventRef out_event;
+ EventTypeSpec event_types[2] = {
+ {kEventClassApplication, kEventAppTerminated},
+ {kEventClassApplication, kEventAppLaunchNotification}};
+
+ q_status_message(SM_ORDER, 0, 4,
+ "Waiting for program to finish, or press a key to stop waiting...");
+ flush_status_messages(1);
+ target = GetEventDispatcherTarget();
+ event_data.done = 0;
+ event_data.set_pid = 0;
+ while(!event_data.done){
+ if((rne_rv = ReceiveNextEvent(2, event_types, 1,
+ true, &out_event)) == noErr){
+ SendEventToEventTarget(out_event, target);
+ ReleaseEvent(out_event);
+ }
+ else if(rne_rv == eventLoopTimedOutErr){
+ ch = read_char(1);
+ if(ch)
+ event_data.done = 1;
+ }
+ else if(rne_rv == eventLoopQuitErr)
+ event_data.done = 1;
+ }
+ our_unlink(image_file);
+ }
+ q_status_message(SM_ORDER, 0, 4, "VIEWER command completed");
+}
+
+pascal OSStatus osx_launch_app_callback(EventHandlerCallRef next_h, EventRef event,void *user_data)
+{
+ EXEC_EVENT_DATA_S *ev_datap = (EXEC_EVENT_DATA_S *)user_data;
+ ProcessSerialNumber pid;
+ Boolean res = 0;
+
+ static int dont_do_anything_yet = 0;
+ switch(GetEventClass(event)){
+ case kEventClassKeyboard:
+ ev_datap->done = 1;
+ break;
+ case kEventClassApplication:
+ switch(GetEventKind(event)){
+ case kEventAppTerminated:
+ GetEventParameter(event,
+ kEventParamProcessID,
+ typeProcessSerialNumber, NULL,
+ sizeof(pid), NULL,
+ &pid);
+ SameProcess(&ev_datap->pid, &pid, &res);
+ if(res){
+ ev_datap->done = 1;
+ ev_datap->set_pid = 0;
+ }
+ break;
+ case kEventAppLaunchNotification:
+ /* could check asyncRef too */
+ if(!ev_datap->set_pid){ /* should always be true */
+ GetEventParameter(event,
+ kEventParamProcessID,
+ typeProcessSerialNumber, NULL,
+ sizeof(ev_datap->pid), NULL,
+ &(ev_datap->pid));
+ ev_datap->set_pid = 1;
+ }
+ break;
+ }
+ break;
+ }
+ return(noErr);
+}
+
+
+int
+install_app_launch_cb(void *user_data)
+{
+ static int already_installed = 0;
+
+ if(!already_installed){
+ EventHandlerUPP cb_upp;
+ EventTypeSpec event_types[2] = {
+ {kEventClassApplication, kEventAppTerminated},
+ {kEventClassApplication, kEventAppLaunchNotification}};
+
+ if((cb_upp = NewEventHandlerUPP(osx_launch_app_callback)) == NULL)
+ return 1;
+ InstallApplicationEventHandler(cb_upp, 2, event_types,
+ user_data, NULL);
+ already_installed = 1;
+ }
+ return 0;
+}
+#endif /* OSX_TARGET */
diff --git a/alpine/osdep/execview.h b/alpine/osdep/execview.h
new file mode 100644
index 00000000..b6406bfc
--- /dev/null
+++ b/alpine/osdep/execview.h
@@ -0,0 +1,27 @@
+/*
+ * $Id: execview.h 761 2007-10-23 22:35:18Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_EXECVIEW_INCLUDED
+#define PINE_OSDEP_EXECVIEW_INCLUDED
+
+#include "../../pith/mailcap.h"
+
+/* exported prototypes */
+void exec_mailcap_cmd(MCAP_CMD_S *, char *, int);
+char *url_os_specified_browser(char *);
+char *execview_pretty_command(MCAP_CMD_S *, int *);
+
+
+#endif /* PINE_OSDEP_EXECVIEW_INCLUDED */
diff --git a/alpine/osdep/fltrname.c b/alpine/osdep/fltrname.c
new file mode 100644
index 00000000..5f2e2185
--- /dev/null
+++ b/alpine/osdep/fltrname.c
@@ -0,0 +1,119 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: fltrname.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#include "../c-client/mail.h" /* for MAILSTREAM */
+#undef ERROR
+
+#include <system.h>
+#include <general.h>
+
+#include "../../pith/osdep/writ_dir.h"
+#include "../../pith/osdep/bldpath.h"
+
+#include "fltrname.h"
+
+
+/*----------------------------------------------------------------------
+ Filter file names for strange characters
+
+ Args: file -- the file name to check
+
+ Result: Returns NULL if file name is OK
+ Returns formatted error message if it is not
+ ----*/
+char *
+filter_filename(char *file, int *fatal, int strict)
+{
+#define ALLOW_WEIRD 1
+#ifdef ALLOW_WEIRD
+ static char illegal[] = {'\177', '\0'};
+#else
+#ifdef _WINDOWS
+ static char illegal[] = {'"', '#', '$', '%', '&', /*'/',*/ '(', ')','*',
+ ',', ';', '<', '=', '>', '?', '[', ']',
+ '^', '|', '\177', '\0'};
+#else /* UNIX */
+ static char illegal[] = {'"', '#', '$', '%', '&', '\'','(', ')','*',
+ ',', ':', ';', '<', '=', '>', '?', '[', ']',
+ '\\', '^', '|', '\177', '\0'};
+#endif /* UNIX */
+#endif
+ static char error[100];
+ char ill_file[MAXPATH+1], *ill_char, *ptr, e2[20];
+ int i;
+
+ for(ptr = file; *ptr == ' '; ptr++) ; /* leading spaces gone */
+
+ while(*ptr && (unsigned char)(*ptr) >= ' ' && strchr(illegal, *ptr) == 0)
+ ptr++;
+
+ *fatal = TRUE;
+ if(*ptr != '\0') {
+ if(*ptr == '\n') {
+ ill_char = "<newline>";
+ } else if(*ptr == '\r') {
+ ill_char = "<carriage return>";
+ } else if(*ptr == '\t') {
+ ill_char = "<tab>";
+ *fatal = FALSE; /* just whitespace */
+ } else if(*ptr < ' ') {
+ snprintf(e2, sizeof(e2), "control-%c", *ptr + '@');
+ ill_char = e2;
+ } else if (*ptr == '\177') {
+ ill_char = "<del>";
+ } else {
+ e2[0] = *ptr;
+ e2[1] = '\0';
+ ill_char = e2;
+ *fatal = FALSE; /* less offensive? */
+ }
+ if(!*fatal){
+ strncpy(error, ill_char, sizeof(error)-1);
+ error[sizeof(error)-1] = '\0';
+ }
+ else if(ptr != file) {
+ strncpy(ill_file, file, MIN(ptr-file,sizeof(ill_file)-1));
+ ill_file[MIN(ptr-file,sizeof(ill_file)-1)] = '\0';
+ snprintf(error, sizeof(error),
+ "Character \"%s\" after \"%.*s\" not allowed in file name",
+ ill_char, sizeof(error)-50, ill_file);
+ } else {
+ snprintf(error, sizeof(error),
+ "First character, \"%s\", not allowed in file name",
+ ill_char);
+ }
+
+ return(error);
+ }
+
+ if((i=is_writable_dir(file)) == 0 || i == 1){
+ snprintf(error, sizeof(error), "\"%.*s\" is a directory", sizeof(error)-50, file);
+ return(error);
+ }
+
+ if(strict){
+ for(ptr = file; *ptr == ' '; ptr++) ; /* leading spaces gone */
+
+ if((ptr[0] == '.' && ptr[1] == '.') || filename_parent_ref(ptr)){
+ snprintf(error, sizeof(error), "\"..\" not allowed in filename");
+ return(error);
+ }
+ }
+
+ return((char *)NULL);
+}
diff --git a/alpine/osdep/fltrname.h b/alpine/osdep/fltrname.h
new file mode 100644
index 00000000..523c641d
--- /dev/null
+++ b/alpine/osdep/fltrname.h
@@ -0,0 +1,26 @@
+/*
+ * $Id: fltrname.h 761 2007-10-23 22:35:18Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_FLTRNAME_INCLUDED
+#define PINE_OSDEP_FLTRNAME_INCLUDED
+
+
+/*
+ * Exported Prototypes
+ */
+char *filter_filename(char *, int *, int);
+
+
+#endif /* PINE_OSDEP_FLTRNAME_INCLUDED */
diff --git a/alpine/osdep/jobcntrl.c b/alpine/osdep/jobcntrl.c
new file mode 100644
index 00000000..38169822
--- /dev/null
+++ b/alpine/osdep/jobcntrl.c
@@ -0,0 +1,55 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: jobcntrl.c 765 2007-10-23 23:51:37Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#include <system.h>
+
+#include "jobcntrl.h"
+
+
+/*----------------------------------------------------------------------
+ This routine returns 1 if job control is available. Note, thiis
+ could be some type of fake job control. It doesn't have to be
+ real BSD-style job control.
+ ----*/
+int
+have_job_control(void)
+{
+ return 1;
+}
+
+
+/*----------------------------------------------------------------------
+ If we don't have job control, this routine is never called.
+ ----*/
+void
+stop_process(void)
+{
+#ifndef _WINDOWS
+ RETSIGTYPE (*save_usr2)(int);
+
+ /*
+ * Since we can't respond to KOD while stopped, the process that sent
+ * the KOD is going to go read-only. Therefore, we can safely ignore
+ * any KODs that come in before we are ready to respond...
+ */
+ save_usr2 = signal(SIGUSR2, SIG_IGN);
+ kill(0, SIGSTOP);
+ (void)signal(SIGUSR2, save_usr2);
+#endif /* !_WINDOWS */
+}
+
+
diff --git a/alpine/osdep/jobcntrl.h b/alpine/osdep/jobcntrl.h
new file mode 100644
index 00000000..3908cce7
--- /dev/null
+++ b/alpine/osdep/jobcntrl.h
@@ -0,0 +1,25 @@
+/*
+ * $Id: jobcntrl.h 761 2007-10-23 22:35:18Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_JOBCNTRL_INCLUDED
+#define PINE_OSDEP_JOBCNTRL_INCLUDED
+
+
+/* exported protoypes */
+int have_job_control(void);
+void stop_process(void);
+
+
+#endif /* PINE_OSDEP_JOBCNTRL_INCLUDED */
diff --git a/alpine/osdep/makefile.wnt b/alpine/osdep/makefile.wnt
new file mode 100644
index 00000000..07afeb63
--- /dev/null
+++ b/alpine/osdep/makefile.wnt
@@ -0,0 +1,66 @@
+# $Id: makefile.wnt 14098 2005-10-03 18:54:13Z jpf@u.washington.edu $
+#
+# ========================================================================
+# Copyright 2006 University of Washington
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# ========================================================================
+
+#
+#
+# Makefile for WIN NT version of the libalpineosd.lib
+#
+#
+CC=cl
+RM=del
+CP=copy
+RC=rc
+
+#includes symbol info for debugging
+CDEBUG= #-Zi -Od
+LDEBUG= /DEBUG /DEBUGTYPE:CV
+
+STDCFLAGS= -I..\..\include -I..\..\regex -nologo -MT -DWIN32 -DDOS -D_WINDOWS -DJOB_CONTROL -DMSC_MALLOC
+
+CFLAGS= $(CDEBUG) $(STDCFLAGS) $(NET) $(EXTRACFLAGS)
+
+LFLAGS= $(LDEBUG) $(EXTRALDFLAGS)
+
+RCFLAGS =
+
+LIBER=lib
+LIBARGS=/nologo /verbose
+
+HFILES= ../../include/system.h ../../include/general.h \
+ debuging.h execview.h fltrname.h jobcntrl.h print.h resource.h termin.gen.h \
+ termin.wnt.h termout.gen.h termout.wnt.h windlg.h
+
+OFILES= chnge_pw.obj debuging.obj diskquot.non.obj execview.obj fltrname.obj \
+ jobcntrl.obj print.obj termin.gen.obj termin.wnt.obj termout.gen.obj \
+ termout.wnt.obj mswinver.obj
+
+all: libalpineosd.lib mswin.res
+
+.c.obj:
+ $(CC) -c $(CFLAGS) "$(MAKEDIR)"\$*.c
+
+$(OFILES): $(HFILES)
+
+libalpineosd.lib: $(OFILES)
+ $(RM) libalpineosd.lib || rem
+ $(LIBER) /out:libalpineosd.lib $(OFILES)
+
+mswin.res: ../../pico/osdep/mswinhnd.cur alpine-splash.bmp resource.h \
+ mswin.rc alpine.ico newmail.ico mclosed.ico
+ $(RC) $(RCFLAGS) /fo mswin.res mswin.rc
+
+
+clean:
+ $(RM) *.lib
+ $(RM) *.obj
+ $(RM) mswin.res
diff --git a/alpine/osdep/mclosed.ico b/alpine/osdep/mclosed.ico
new file mode 100644
index 00000000..0c6306b3
--- /dev/null
+++ b/alpine/osdep/mclosed.ico
Binary files differ
diff --git a/alpine/osdep/mswin.def b/alpine/osdep/mswin.def
new file mode 100644
index 00000000..0b262412
--- /dev/null
+++ b/alpine/osdep/mswin.def
@@ -0,0 +1,17 @@
+NAME PINE
+EXETYPE WINDOWS
+DESCRIPTION 'PC-Pine for Windows (Character)'
+STUB 'winstub.exe'
+
+CODE PRELOAD DISCARDABLE SHARED
+DATA PRELOAD MULTIPLE
+
+HEAPSIZE 100
+
+EXPORTS
+ PWNDPROC @1
+ TWWNDPROC @2
+ ABOUTDLGPROC @3
+
+
+
diff --git a/alpine/osdep/mswin.rc b/alpine/osdep/mswin.rc
new file mode 100644
index 00000000..b4a8533a
--- /dev/null
+++ b/alpine/osdep/mswin.rc
@@ -0,0 +1,605 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+ALPINEICON ICON DISCARDABLE "ALPINE.ICO"
+NEWMAILICON ICON DISCARDABLE "NEWMAIL.ICO"
+MCLOSEDICON ICON DISCARDABLE "MCLOSED.ICO"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+ALPINESPLASH BITMAP MOVEABLE PURE "ALPINE-SPLASH.BMP"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Cursor
+//
+
+PICOHAND CURSOR "..\..\PICO\OSDEP\MSWINHND.CUR"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+ALPINEMENU MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Print", IDM_MI_PRINT
+ MENUITEM SEPARATOR
+ MENUITEM "&Read File", IDM_MI_READFILE
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_MI_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "Cu&t\tCtrl-Shift-X", IDM_EDIT_CUT
+ MENUITEM "&Copy\tCtrl-Shift-C", IDM_EDIT_COPY
+ MENUITEM "Copy Append\tCtrl-Alt-C", IDM_EDIT_COPY_APPEND
+ MENUITEM "&Paste\tCtrl-Shift-V", IDM_EDIT_PASTE
+ MENUITEM "Cance&l Paste!\tCtrl-Alt-V", IDM_EDIT_CANCEL_PASTE
+ MENUITEM SEPARATOR
+ MENUITEM "&Find\tCtrl-Shift-F", IDM_MI_WHEREIS
+ END
+ POPUP "&Go"
+ BEGIN
+ MENUITEM "&Main Menu", IDM_MI_MAINMENU
+ MENUITEM "&List Folders", IDM_MI_FLDRLIST
+ MENUITEM "&Index", IDM_MI_FLDRINDEX
+ MENUITEM "&Goto Folder", IDM_MI_GOTOFLDR
+ MENUITEM "E&xit Current Mode", IDM_MI_EXITMODE
+ MENUITEM SEPARATOR
+ MENUITEM "&Previous Message", IDM_MI_PREVMSG
+ MENUITEM "&Next Message", IDM_MI_NEXTMSG
+ MENUITEM "&Jump To Message", IDM_MI_JUMPTOMSG
+ MENUITEM "&Where Is", IDM_MI_WHEREIS
+ END
+ POPUP "&Message"
+ BEGIN
+ MENUITEM "&View", IDM_MI_VIEW
+ MENUITEM "ViewInNew&Window", IDM_MI_VIEWINWIND
+ MENUITEM "Pr&int", IDM_MI_PRINT
+ MENUITEM "&Save", IDM_MI_SAVE
+ MENUITEM "&Export", IDM_MI_EXPORT
+ MENUITEM SEPARATOR
+ MENUITEM "&Delete", IDM_MI_DELETE
+ POPUP "&Flag"
+ BEGIN
+ MENUITEM "&Important", IDM_MI_FLAGIMPORTANT
+ MENUITEM "&New", IDM_MI_FLAGNEW
+ MENUITEM "&Answered", IDM_MI_FLAGANSWERED
+ MENUITEM "&Deleted", IDM_MI_FLAGDELETED
+ END
+ MENUITEM "E&xpunge", IDM_MI_EXPUNGE
+ MENUITEM SEPARATOR
+ MENUITEM "&Take Address", IDM_MI_TAKEADDR
+ MENUITEM "&Header Mode", IDM_MI_HDRMODE
+ POPUP "S&ort"
+ BEGIN
+ MENUITEM "Arrival", IDM_MI_SORTARRIVAL
+ MENUITEM "Date", IDM_MI_SORTDATE
+ MENUITEM "From", IDM_MI_SORTFROM
+ MENUITEM "To", IDM_MI_SORTTO
+ MENUITEM "Cc", IDM_MI_SORTCC
+ MENUITEM "Subject", IDM_MI_SORTSUBJECT
+ MENUITEM "OrderedSubject", IDM_MI_SORTORDERSUB
+ MENUITEM "Size", IDM_MI_SORTSIZE
+ MENUITEM "Score", IDM_MI_SORTSCORE
+ MENUITEM "Thread", IDM_MI_SORTTHREAD
+ MENUITEM SEPARATOR
+ MENUITEM "Reverse", IDM_MI_SORTREVERSE
+ END
+ MENUITEM "Se&lect", IDM_MI_SELECT
+ MENUITEM "&Apply", IDM_MI_APPLY
+ MENUITEM "&Zoom", IDM_MI_ZOOM
+ END
+ POPUP "&Send"
+ BEGIN
+ MENUITEM "&Compose Message", IDM_MI_COMPOSER
+ MENUITEM "&Reply", IDM_MI_REPLY
+ MENUITEM "&Forward", IDM_MI_FORWARD
+ MENUITEM "&Bounce", IDM_MI_BOUNCE
+ END
+ POPUP "&Config"
+ BEGIN
+ MENUITEM "Set &Window Font", IDM_OPT_SETFONT
+ MENUITEM "Print Font &Same As Window", IDM_OPT_FONTSAMEAS
+ MENUITEM "Set &Printer Font", IDM_OPT_SETPRINTFONT
+ MENUITEM SEPARATOR
+ MENUITEM "&Toolbar", IDM_OPT_TOOLBAR
+ MENUITEM "Tool&bar on Top", IDM_OPT_TOOLBARPOS
+ POPUP "&Cursor"
+ BEGIN
+ MENUITEM "Block", IDM_OPT_CARETBLOCK
+ MENUITEM "Small Block", IDM_OPT_CARETSMALLBLOCK
+ MENUITEM "Underline", IDM_OPT_CARETHBAR
+ MENUITEM "Vertical Bar", IDM_OPT_CARETVBAR
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Use &Dialog Boxes", IDM_OPT_USEDIALOGS
+ MENUITEM "Erase Preserved &Passwords", IDM_OPT_ERASE_CREDENTIALS
+ MENUITEM SEPARATOR
+ MENUITEM "&IMAP Telemetry", IDM_OPT_IMAPTELEM
+ MENUITEM "&New Mail Window", IDM_OPT_NEWMAILWIN
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&Screen Help", IDM_MI_SCREENHELP
+ MENUITEM "&About", IDM_ABOUT
+ END
+END
+
+TEXTWINMENU MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Print", IDM_FILE_PRINT
+ MENUITEM SEPARATOR
+ MENUITEM "&Close", IDM_FILE_CLOSE
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "&Copy\tCtrl-Shift-C", IDM_EDIT_COPY
+ MENUITEM "Select All", IDM_EDIT_SEL_ALL
+ END
+END
+
+COMPOSERMENU MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Print", IDM_MI_PRINT
+ MENUITEM SEPARATOR
+ MENUITEM "&Read File", 181
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_MI_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "Cu&t\tCtrl-Shift-X", IDM_EDIT_CUT
+ MENUITEM "&Copy\tCtrl-Shift-C", IDM_EDIT_COPY
+ MENUITEM "Copy Append\tCtrl-Alt-C", IDM_EDIT_COPY_APPEND
+ MENUITEM "&Paste\tCtrl-Shift-V", IDM_EDIT_PASTE
+ MENUITEM "Cance&l Paste!\tCtrl-Alt-V", IDM_EDIT_CANCEL_PASTE
+ MENUITEM SEPARATOR
+ MENUITEM "Select &All", IDM_EDIT_SEL_ALL
+ MENUITEM SEPARATOR
+ MENUITEM "&Find\tCtrl-Shift-F", IDM_MI_WHEREIS
+ MENUITEM SEPARATOR
+ MENUITEM "&Spell", IDM_MI_SPELLCHK
+ END
+ POPUP "&Compose"
+ BEGIN
+ MENUITEM "P&ostpone", IDM_MI_POSTPONE
+ MENUITEM "&Send", IDM_MI_SEND
+ MENUITEM "&Cancel", IDM_MI_CANCEL
+ MENUITEM SEPARATOR
+ MENUITEM "&Attach", IDM_MI_ATTACH
+ MENUITEM "Rich &Headers", IDM_MI_RICHHDR
+ MENUITEM "&To Address Book", IDM_MI_TOADDRBOOK
+ MENUITEM SEPARATOR
+ MENUITEM "&Justify Paragraph", IDM_MI_JUSTIFY
+ MENUITEM "Run Alternate &Editor", IDM_MI_ALTEDITOR
+ END
+ POPUP "C&onfig"
+ BEGIN
+ MENUITEM "Set &Window Font", IDM_OPT_SETFONT
+ MENUITEM "Print Font &Same As Window", IDM_OPT_FONTSAMEAS
+ MENUITEM "Set &Printer Font", IDM_OPT_SETPRINTFONT
+ MENUITEM SEPARATOR
+ MENUITEM "&Toolbar", IDM_OPT_TOOLBAR
+ MENUITEM "Tool&bar on Top", IDM_OPT_TOOLBARPOS
+ POPUP "&Cursor"
+ BEGIN
+ MENUITEM "Block", IDM_OPT_CARETBLOCK
+ MENUITEM "Small Block", IDM_OPT_CARETSMALLBLOCK
+ MENUITEM "Underline", IDM_OPT_CARETHBAR
+ MENUITEM "Vertical Bar", IDM_OPT_CARETVBAR
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Use &Dialog Boxes", IDM_OPT_USEDIALOGS
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&Screen Help", IDM_MI_SCREENHELP
+ MENUITEM "&About", IDM_ABOUT
+ END
+END
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 2,01,0,0
+ PRODUCTVERSION 2,01,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "see http://www.washington.edu/alpine\0"
+ VALUE "CompanyName", "University of Washington\0"
+#ifdef _PCP_W2K
+ VALUE "FileDescription", "Alpine with krb5 for Windows\0"
+#else
+ VALUE "FileDescription", "Alpine\0"
+#endif
+ VALUE "FileVersion", "2.10\0"
+ VALUE "InternalName", "alpine\0"
+ VALUE "LegalCopyright", "Copyright 2006-2009\0"
+ VALUE "OriginalFilename", "alpine.exe\0"
+ VALUE "ProductName", "alpine\0"
+ VALUE "ProductVersion", "2.10\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+#include "..\..\pico\osdep\mswin_spell.dlg"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+ABOUTDLGBOX DIALOGEX 10, 25, 217, 80
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Alpine"
+FONT 8, "Helv", 0, 0, 0x1
+BEGIN
+ CTEXT "Alpine for Windows%S\nVersion %d.%d%S\nBuild (%S)",
+ IDD_VERSION,47,12,110,26,SS_NOPREFIX | NOT WS_GROUP,
+ WS_EX_TRANSPARENT
+ LTEXT "",IDD_BYLINE,21,46,172,56,SS_NOPREFIX | NOT WS_GROUP
+ DEFPUSHBUTTON "OK",IDD_OK,159,15,40,14
+ ICON ALPINEICON,IDC_STATIC,25,15,20,20
+END
+
+SPLASHDLGBOX DIALOGEX 0, 0, 520, 316
+STYLE WS_POPUP | DS_SETFOREGROUND | DS_LOCALEDIT
+BEGIN
+END
+
+IDD_TOOLBAR DIALOG DISCARDABLE 0, 0, 311, 12
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+ PUSHBUTTON "Quit",IDM_MI_EXIT,1,1,25,11,NOT WS_TABSTOP
+ PUSHBUTTON "Main Menu",IDM_MI_MAINMENU,26,1,40,11,NOT WS_TABSTOP
+ PUSHBUTTON "Folders",IDM_MI_FLDRLIST,66,1,29,11,NOT WS_TABSTOP
+ PUSHBUTTON "Index",IDM_MI_FLDRINDEX,95,1,25,11,NOT WS_TABSTOP
+ PUSHBUTTON "View",IDM_MI_VIEW,120,1,24,11,NOT WS_TABSTOP
+ PUSHBUTTON "Compose",IDM_MI_COMPOSER,144,1,37,11,NOT WS_TABSTOP
+ PUSHBUTTON "Reply",IDM_MI_REPLY,181,1,27,11,NOT WS_TABSTOP
+ PUSHBUTTON "Forward",IDM_MI_FORWARD,208,1,34,11,NOT WS_TABSTOP
+END
+
+IDD_COMPOSER_TB DIALOG DISCARDABLE 0, 0, 311, 12
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+ PUSHBUTTON "Send",IDM_MI_SEND,1,1,25,11
+ PUSHBUTTON "Cancel",IDM_MI_CANCEL,26,1,29,11
+ PUSHBUTTON "Postpone",IDM_MI_POSTPONE,55,1,37,11
+ PUSHBUTTON "Attach",IDM_MI_ATTACH,92,1,29,11
+ PUSHBUTTON "Find",IDM_MI_WHEREIS,121,1,22,11
+ PUSHBUTTON "Spell",IDM_MI_SPELLCHK,143,1,23,11
+END
+
+IDD_OPTIONALYENTER DIALOG DISCARDABLE 30, 30, 255, 86
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Alpine"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,7,52,79,14
+ PUSHBUTTON "Cancel",IDCANCEL,7,68,78,14
+ LTEXT "",IDC_PROMPT,6,9,231,18
+ EDITTEXT IDC_RESPONCE,3,33,237,12,ES_AUTOHSCROLL | ES_NOHIDESEL
+ DEFPUSHBUTTON "Help '^G'",IDC_GETHELP,87,52,79,14
+END
+
+IDD_LOGINDLG DIALOG DISCARDABLE 0, 0, 213, 111
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_MINIMIZEBOX |
+ WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Alpine Login"
+FONT 8, "MS Sans Serif"
+BEGIN
+ ICON ALPINEICON,IDC_STATIC,7,10,21,20
+ LTEXT "Authentication required.",IDC_STATIC,44,12,152,8
+ LTEXT "Host :",IDC_PROMPT,44,23,165,8
+ LTEXT "Login: ",IDC_STATIC,20,44,20,8
+ EDITTEXT IDC_RLOGINE,45,42,133,12,ES_AUTOHSCROLL
+ LTEXT "Password: ",IDC_RPWTEXT,7,57,36,8
+ EDITTEXT IDC_RPASSWORD,45,55,133,12,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "Preserve this password for future logins",
+ IDC_PRESPASS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,70,
+ 165,8
+ DEFPUSHBUTTON "OK",IDOK,47,90,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,106,90,50,14
+END
+
+IDD_LOGINDLG2 DIALOG DISCARDABLE 0, 0, 281, 222
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_MINIMIZEBOX |
+ WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Alpine Login"
+FONT 8, "MS Sans Serif"
+BEGIN
+ ICON ALPINEICON,IDC_STATIC,7,10,21,20
+ LTEXT "Authentication required.\n\nIn order to set up Alpine, please authenticate to the IMAP server where your configuration will be stored.",IDC_STATIC,44,24,180,50
+ LTEXT "Host:",IDC_PROMPT,59,80,165,8
+ LTEXT "Login: ",IDC_STATIC,57,98,20,8
+ EDITTEXT IDC_RLOGINE,82,96,133,12,ES_AUTOHSCROLL
+ LTEXT "Password: ",IDC_RPWTEXT,44,120,36,8
+ EDITTEXT IDC_RPASSWORD,82,118,133,12,ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "Preserve this password for future logins",
+ IDC_PRESPASS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,82,138,
+ 165,8
+ DEFPUSHBUTTON "OK",IDOK,65,196,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,131,196,50,14
+END
+
+
+IDD_CONFIGDLG DIALOG DISCARDABLE 0, 0, 281, 222
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_MINIMIZEBOX |
+ WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Alpine Configuration Setup"
+FONT 8, "MS Sans Serif"
+BEGIN
+ ICON ALPINEICON,IDC_STATIC,7,10,21,20
+ LTEXT "Alpine was not able to locate your personal configuration file. Please specify where Alpine should look for (or create) it.",
+ IDC_CONFTEXT,45,14,211,17
+ GROUPBOX "",IDC_STATIC,10,34,259,88
+ CONTROL "Use configuration file stored on IMAP server",
+ IDC_CONFRRADIO,"Button",BS_AUTORADIOBUTTON,17,42,154,10
+ LTEXT "IMAP Server :",IDC_CONFSRVRTXT,31,54,45,8
+ EDITTEXT IDC_CONFESERVER,77,52,138,14,ES_AUTOHSCROLL
+ LTEXT "Username :",IDC_CONFUNTXT,115,70,37,8
+ EDITTEXT IDC_CONFEUSERNAME,154,68,62,14,ES_AUTOHSCROLL
+ CONTROL "Use default configuration folder name",IDC_CONFDFLTFLDR,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,31,89,133,10
+ LTEXT "Configuration folder name :",IDC_CONFFLDRTXT,31,104,85,8
+ EDITTEXT IDC_CONFEFLDRNAME,117,102,86,14,ES_AUTOHSCROLL
+ GROUPBOX "",IDC_STATIC,11,126,259,43
+ CONTROL "Use local configuration file",IDC_CONFLRADIO,"Button",
+ BS_AUTORADIOBUTTON,17,135,99,10
+ LTEXT "Configuration file name :",IDC_CONFFNTXT,34,148,76,8
+ EDITTEXT IDC_CONFEFN,113,146,89,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Browse",IDC_CONFBROWSE,207,145,50,14
+ CONTROL "Use this as the default Alpine Configuration",
+ IDC_CONFDFLTSET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,178,
+ 157,10
+ DEFPUSHBUTTON "OK",IDOK,65,196,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,131,196,50,14
+END
+
+IDD_CFVARSDLG DIALOG DISCARDABLE 0, 0, 281, 222
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_MINIMIZEBOX |
+ WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Alpine Configuration Setup"
+FONT 8, "MS Sans Serif"
+BEGIN
+ ICON ALPINEICON,IDC_STATIC,7,10,21,20
+ LTEXT "In order to properly set up Alpine, please fill out the following information, which can also be provided later.",
+ IDC_STATIC,45,14,211,17
+ LTEXT "Personal Name :",IDC_STATIC,33,46,53,8
+ EDITTEXT IDC_CFV_PNAME,90,43,157,14,ES_AUTOHSCROLL
+ LTEXT "Email Address :",IDC_STATIC,37,66,49,8
+ EDITTEXT IDC_CFV_EMAILADR,90,63,157,14,ES_AUTOHSCROLL
+ LTEXT "Mail Server :",IDC_STATIC,45,86,41,8
+ EDITTEXT IDC_CFV_MSERVER,90,83,157,14,ES_AUTOHSCROLL
+ CONTROL "This server is an IMAP server",IDC_CFV_IMAP,"Button",
+ BS_AUTORADIOBUTTON,141,100,108,10
+ CONTROL "This server is a POP3 server",IDC_CFV_POP3,"Button",
+ BS_AUTORADIOBUTTON,141,113,105,10
+ LTEXT "Login name (optional) :",IDC_STATIC,120,129,72,8
+ EDITTEXT IDC_CFV_LOGIN,195,126,51,14,ES_AUTOHSCROLL
+ LTEXT "SMTP Server :",IDC_STATIC,39,149,48,8
+ EDITTEXT IDC_CFV_SMTPSERVER,90,146,157,14,ES_AUTOHSCROLL
+ CONTROL "Make Alpine the default E-mail reader",
+ IDC_CFV_DEFMAILER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 90,165,157,10
+ CONTROL "Make Alpine the default Newsgroup reader",
+ IDC_CFV_DEFNEWSRDR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 90,177,157,10
+ DEFPUSHBUTTON "OK",IDOK,65,196,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,131,196,50,14
+END
+
+IDD_SELECT DIALOG DISCARDABLE 30, 30, 255, 66
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Alpine"
+FONT 8, "MS Sans Serif"
+BEGIN
+ PUSHBUTTON "Help",IDC_GETHELP,7,50,78,14
+ PUSHBUTTON "Cancel",IDCANCEL,7,33,78,14
+ LTEXT "",IDC_PROMPT,7,7,231,22
+ CONTROL "User1",IDC_RESPONCE,"KeyboardCapture",NOT WS_VISIBLE,
+ 208,49,35,12
+END
+
+IDD_SELECTSORT DIALOG DISCARDABLE 30, 30, 170, 102
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Select Sort"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Arrival",IDC_SORTARRIVAL,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP | WS_TABSTOP,11,6,74,9
+ CONTROL "From",IDC_SORTFROM,"Button",BS_AUTORADIOBUTTON |
+ WS_TABSTOP,96,6,74,9
+ CONTROL "Subject",IDC_SORTSUBJECT,"Button",BS_AUTORADIOBUTTON |
+ WS_TABSTOP,11,18,74,9
+ CONTROL "To",IDC_SORTTO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
+ 96,18,74,9
+ CONTROL "Ordered Subject",IDC_SORTORDERSUB,"Button",
+ BS_AUTORADIOBUTTON | WS_TABSTOP,11,30,74,9
+ CONTROL "Cc",IDC_SORTCC,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
+ 96,30,74,9
+ CONTROL "Size",IDC_SORTSIZE,"Button",BS_AUTORADIOBUTTON |
+ WS_TABSTOP,11,42,74,9
+ CONTROL "Date",IDC_SORTDATE,"Button",BS_AUTORADIOBUTTON |
+ WS_TABSTOP,96,42,74,9
+ CONTROL "Thread",IDC_SORTTHREAD,"Button",BS_AUTORADIOBUTTON |
+ WS_TABSTOP,11,54,74,9
+ CONTROL "Score",IDC_SORTSCORE,"Button",BS_AUTORADIOBUTTON |
+ WS_TABSTOP,96,54,74,9
+ CONTROL "Reverse Sort",IDC_SORTREVERSE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,55,67,58,12
+ DEFPUSHBUTTON "OK",IDOK,5,82,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,60,82,50,14
+ PUSHBUTTON "Help",IDC_GETHELP,115,82,50,14
+END
+
+IDD_SELECTFLAG DIALOG DISCARDABLE 30, 30, 134, 42
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Select Flags"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,11,22,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,72,22,50,14
+ CONTROL "Flag 1",IDC_FLAGCOL1,"Button",BS_AUTOCHECKBOX | NOT
+ WS_VISIBLE | WS_TABSTOP,4,4,59,10
+ CONTROL "Flag 2",IDC_FLAGCOL2,"Button",BS_AUTOCHECKBOX | NOT
+ WS_VISIBLE | WS_TABSTOP,70,4,59,10
+END
+
+IDD_ARGLIST DIALOG DISCARDABLE 0, 0, 302, 223
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Alpine - Command Line Arguments"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,124,196,50,14,BS_CENTER
+ EDITTEXT IDC_ARGTEXT,7,7,287,182,ES_MULTILINE | ES_AUTOHSCROLL |
+ ES_READONLY | WS_VSCROLL | WS_HSCROLL
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ARGLIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 295
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 414
+ HORZGUIDE, 160
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_BYLINE "Copyright 2006-2009 University of Washington"
+ IDS_APPNAME "Alpine"
+ IDS_APPIDENT "alpine"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/alpine/osdep/mswinver.c b/alpine/osdep/mswinver.c
new file mode 100644
index 00000000..0c683520
--- /dev/null
+++ b/alpine/osdep/mswinver.c
@@ -0,0 +1,74 @@
+/*
+ * ========================================================================
+ * Copyright 2006-2009 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#define VER_MAJOR 2
+#define VER_MINOR 1
+extern char datestamp[];
+
+
+/*
+ * Return major version number...
+ */
+int
+mswin_majorver()
+{
+ return(VER_MAJOR);
+}
+
+
+/*
+ * Return minor version number...
+ */
+int
+mswin_minorver()
+{
+ return(VER_MINOR);
+}
+
+
+/*
+ * Return compilation number...
+ */
+char *
+mswin_compilation_date()
+{
+ return(datestamp);
+}
+
+
+/*
+ * Return special remarks...
+ */
+char *
+mswin_compilation_remarks()
+{
+#ifdef SPCL_REMARKS
+ return(SPCL_REMARKS);
+#else
+ return("");
+#endif
+}
+
+/*
+ * Return specific windows version...
+ */
+char *
+mswin_specific_winver()
+{
+#ifdef SPCFC_WINVER
+ return(SPCFC_WINVER);
+#else
+ return("");
+#endif
+}
diff --git a/alpine/osdep/newmail.ico b/alpine/osdep/newmail.ico
new file mode 100644
index 00000000..47783cb8
--- /dev/null
+++ b/alpine/osdep/newmail.ico
Binary files differ
diff --git a/alpine/osdep/print.c b/alpine/osdep/print.c
new file mode 100644
index 00000000..01720ece
--- /dev/null
+++ b/alpine/osdep/print.c
@@ -0,0 +1,529 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: print.c 942 2008-03-04 18:21:33Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2008 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+#include <system.h>
+#include <general.h>
+
+#include "../c-client/mail.h" /* for MAILSTREAM and friends */
+#include "../c-client/osdep.h"
+#include "../c-client/rfc822.h" /* for soutr_t and such */
+#include "../c-client/misc.h" /* for cpystr proto */
+#include "../c-client/utf8.h" /* for CHARSET and such*/
+#include "../c-client/imap4r1.h"
+
+#include "../../pith/charconv/utf8.h"
+#include "../../pith/charconv/filesys.h"
+
+#include "../../pith/osdep/color.h"
+#include "../../pith/osdep/temp_nam.h"
+#include "../../pith/osdep/err_desc.h"
+#include "../../pith/osdep/collate.h"
+
+#include "../../pith/debug.h"
+#include "../../pith/conf.h"
+#include "../../pith/store.h"
+#include "../../pith/filttype.h"
+
+#include "../../pico/estruct.h" /* for ctrl() */
+#include "../../pico/keydefs.h" /* for KEY_* */
+
+#include "../status.h"
+#include "../signal.h"
+#include "../radio.h"
+#include "../../pico/estruct.h"
+#include "../../pico/pico.h"
+#include "../mailview.h"
+
+#ifdef _WINDOWS
+#include "../../pico/osdep/mswin.h"
+#endif
+
+#include "../../pico/osdep/raw.h"
+
+#include "termin.gen.h"
+
+#include "print.h"
+
+
+/*======================================================================
+ print routines
+
+ Functions having to do with printing on paper and forking of spoolers
+
+ In general one calls open_printer() to start printing. One of
+ the little print functions to send a line or string, and then
+ call print_end() when complete. This takes care of forking off a spooler
+ and piping the stuff down it. No handles or anything here because there's
+ only one printer open at a time.
+
+ ====*/
+
+
+
+#ifndef _WINDOWS
+static char *trailer; /* so both open and close_printer can see it */
+static int ansi_off;
+static CBUF_S cb;
+#endif /* !_WINDOWS */
+
+
+/*----------------------------------------------------------------------
+ Open the printer
+
+ Args: desc -- Description of item to print. Should have one trailing blank.
+
+ Return value: < 0 is a failure.
+ 0 a success.
+
+This does most of the work of popen so we can save the standard output of the
+command we execute and send it back to the user.
+ ----*/
+int
+open_printer(char *desc)
+{
+#ifndef _WINDOWS
+ char command[201], prompt[200];
+ int cmd, rc, just_one;
+ char *p, *init, *nick;
+ char aname[100], wname[100];
+ char *printer;
+ int done = 0, i, lastprinter, cur_printer = 0;
+ HelpType help;
+ char **list;
+ static ESCKEY_S ekey[] = {
+ /* TRANSLATORS: these are command labels for printing screen */
+ {'y', 'y', "Y", N_("Yes")},
+ {'n', 'n', "N", N_("No")},
+ /* TRANSLATORS: go to Previous Printer in list */
+ {ctrl('P'), 10, "^P", N_("Prev Printer")},
+ {ctrl('N'), 11, "^N", N_("Next Printer")},
+ {-2, 0, NULL, NULL},
+ /* TRANSLATORS: use Custom Print command */
+ {'c', 'c', "C", N_("CustomPrint")},
+ {KEY_UP, 10, "", ""},
+ {KEY_DOWN, 11, "", ""},
+ {-1, 0, NULL, NULL}};
+#define PREV_KEY 2
+#define NEXT_KEY 3
+#define CUSTOM_KEY 5
+#define UP_KEY 6
+#define DOWN_KEY 7
+
+ trailer = NULL;
+ init = NULL;
+ nick = NULL;
+ command[sizeof(command)-1] = '\0';
+
+ if(ps_global->VAR_PRINTER == NULL){
+ q_status_message(SM_ORDER | SM_DING, 3, 5,
+ "No printer has been chosen. Use SETUP on main menu to make choice.");
+ return(-1);
+ }
+
+ /* Is there just one print command available? */
+ just_one = (ps_global->printer_category!=3&&ps_global->printer_category!=2)
+ || (ps_global->printer_category == 2
+ && !(ps_global->VAR_STANDARD_PRINTER
+ && ps_global->VAR_STANDARD_PRINTER[0]
+ && ps_global->VAR_STANDARD_PRINTER[1]))
+ || (ps_global->printer_category == 3
+ && !(ps_global->VAR_PERSONAL_PRINT_COMMAND
+ && ps_global->VAR_PERSONAL_PRINT_COMMAND[0]
+ && ps_global->VAR_PERSONAL_PRINT_COMMAND[1]));
+
+ if(F_ON(F_CUSTOM_PRINT, ps_global))
+ ekey[CUSTOM_KEY].ch = 'c'; /* turn this key on */
+ else
+ ekey[CUSTOM_KEY].ch = -2; /* turn this key off */
+
+ if(just_one){
+ ekey[PREV_KEY].ch = -2; /* turn these keys off */
+ ekey[NEXT_KEY].ch = -2;
+ ekey[UP_KEY].ch = -2;
+ ekey[DOWN_KEY].ch = -2;
+ }
+ else{
+ ekey[PREV_KEY].ch = ctrl('P'); /* turn these keys on */
+ ekey[NEXT_KEY].ch = ctrl('N');
+ ekey[UP_KEY].ch = KEY_UP;
+ ekey[DOWN_KEY].ch = KEY_DOWN;
+ /*
+ * count how many printers in list and find the default in the list
+ */
+ if(ps_global->printer_category == 2)
+ list = ps_global->VAR_STANDARD_PRINTER;
+ else
+ list = ps_global->VAR_PERSONAL_PRINT_COMMAND;
+
+ for(i = 0; list[i]; i++)
+ if(strcmp(ps_global->VAR_PRINTER, list[i]) == 0)
+ cur_printer = i;
+
+ lastprinter = i - 1;
+ }
+
+ help = NO_HELP;
+ ps_global->mangled_footer = 1;
+
+ while(!done){
+ if(init)
+ fs_give((void **)&init);
+
+ if(trailer)
+ fs_give((void **)&trailer);
+
+ if(just_one)
+ printer = ps_global->VAR_PRINTER;
+ else
+ printer = list[cur_printer];
+
+ parse_printer(printer, &nick, &p, &init, &trailer, NULL, NULL);
+ strncpy(command, p, sizeof(command)-1);
+ command[sizeof(command)-1] = '\0';
+ fs_give((void **)&p);
+ /* TRANSLATORS: Print something1 using something2.
+ For example, Print configuration using printer three. */
+ snprintf(prompt, sizeof(prompt), _("Print %s using \"%s\" ? "),
+ desc ? desc : "",
+ *nick ? nick : command);
+ prompt[sizeof(prompt)-1] = '\0';
+
+ fs_give((void **)&nick);
+
+ cmd = radio_buttons(prompt, -FOOTER_ROWS(ps_global),
+ ekey, 'y', 'x', help, RB_NORM);
+
+ switch(cmd){
+ case 'y':
+ q_status_message1(SM_ORDER, 0, 9,
+ "Printing with command \"%s\"", command);
+ done++;
+ break;
+
+ case 10:
+ cur_printer = (cur_printer>0)
+ ? (cur_printer-1)
+ : lastprinter;
+ break;
+
+ case 11:
+ cur_printer = (cur_printer<lastprinter)
+ ? (cur_printer+1)
+ : 0;
+ break;
+
+ case 'n':
+ case 'x':
+ done++;
+ break;
+
+ case 'c':
+ done++;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if(cmd == 'c'){
+ if(init)
+ fs_give((void **)&init);
+
+ if(trailer)
+ fs_give((void **)&trailer);
+
+ snprintf(prompt, sizeof(prompt), "Enter custom command : ");
+ prompt[sizeof(prompt)-1] = '\0';
+ command[0] = '\0';
+ rc = 1;
+ help = NO_HELP;
+ while(rc){
+ int flags = OE_APPEND_CURRENT;
+
+ rc = optionally_enter(command, -FOOTER_ROWS(ps_global), 0,
+ sizeof(command), prompt, NULL, help, &flags);
+
+ if(rc == 1){
+ cmd = 'x';
+ rc = 0;
+ }
+ else if(rc == 3)
+ help = (help == NO_HELP) ? h_custom_print : NO_HELP;
+ else if(rc == 0){
+ removing_trailing_white_space(command);
+ removing_leading_white_space(command);
+ q_status_message1(SM_ORDER, 0, 9,
+ "Printing with command \"%s\"", command);
+ }
+ }
+ }
+
+ if(cmd == 'x' || cmd == 'n'){
+ q_status_message(SM_ORDER, 0, 2, "Print cancelled");
+ if(init)
+ fs_give((void **)&init);
+
+ if(trailer)
+ fs_give((void **)&trailer);
+
+ return(-1);
+ }
+
+ display_message('x');
+
+ ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S));
+ memset(ps_global->print, 0, sizeof(PRINT_S));
+
+ strncpy(aname, ANSI_PRINTER, sizeof(aname)-1);
+ aname[sizeof(aname)-1] = '\0';
+ strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
+ strncpy(wname, WYSE_PRINTER, sizeof(wname)-1);
+ wname[sizeof(wname)-1] = '\0';
+ strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
+ if(strucmp(command, ANSI_PRINTER) == 0
+ || strucmp(command, aname) == 0
+ || strucmp(command, WYSE_PRINTER) == 0
+ || strucmp(command, wname) == 0){
+ /*----------- Attached printer ---------*/
+ q_status_message(SM_ORDER, 0, 9,
+ "Printing to attached desktop printer...");
+ display_message('x');
+ xonxoff_proc(1); /* make sure XON/XOFF used */
+ crlf_proc(1); /* AND LF->CR xlation */
+ if(strucmp(command, ANSI_PRINTER) == 0
+ || strucmp(command, aname) == 0){
+ fputs("\033[5i", stdout);
+ ansi_off = 1;
+ }
+ else{
+ ansi_off = 0;
+ printf("%c", 18); /* aux on for wyse60,
+ Chuck Everett <ceverett@odessa.edu> */
+ }
+
+ ps_global->print->fp = stdout;
+ if(strucmp(command, ANSI_PRINTER) == 0
+ || strucmp(command, WYSE_PRINTER) == 0){
+ /* put formfeed at the end of the trailer string */
+ if(trailer){
+ int len = strlen(trailer);
+
+ fs_resize((void **)&trailer, len+2);
+ trailer[len] = '\f';
+ trailer[len+1] = '\0';
+ }
+ else
+ trailer = cpystr("\f");
+ }
+ }
+ else{
+ /*----------- Print by forking off a UNIX command ------------*/
+ dprint((4, "Printing using command \"%s\"\n",
+ command ? command : "?"));
+ ps_global->print->result = temp_nam(NULL, "pine_prt");
+ if(ps_global->print->result &&
+ (ps_global->print->pipe = open_system_pipe(command,
+ &ps_global->print->result, NULL,
+ PIPE_WRITE | PIPE_STDERR, 0,
+ pipe_callback, NULL))){
+ ps_global->print->fp = ps_global->print->pipe->out.f;
+ }
+ else{
+ if(ps_global->print->result){
+ our_unlink(ps_global->print->result);
+ fs_give((void **)&ps_global->print->result);
+ }
+
+ q_status_message1(SM_ORDER | SM_DING, 3, 4,
+ "Error opening printer: %s",
+ error_description(errno));
+ dprint((2, "Error popening printer \"%s\"\n",
+ error_description(errno)));
+ if(init)
+ fs_give((void **)&init);
+
+ if(trailer)
+ fs_give((void **)&trailer);
+
+ return(-1);
+ }
+ }
+
+ ps_global->print->err = 0;
+ if(init){
+ if(*init)
+ fputs(init, ps_global->print->fp);
+
+ fs_give((void **)&init);
+ }
+
+ cb.cbuf[0] = '\0';
+ cb.cbufp = cb.cbuf;
+ cb.cbufend = cb.cbuf;
+#else /* _WINDOWS */
+ int status;
+ LPTSTR desclpt = NULL;
+
+ if(desc)
+ desclpt = utf8_to_lptstr(desc);
+
+ if (status = mswin_print_ready (0, desclpt)) {
+ q_status_message1(SM_ORDER | SM_DING, 3, 4,
+ "Error starting print job: %s",
+ mswin_print_error(status));
+ if(desclpt)
+ fs_give((void **) &desclpt);
+
+ return(-1);
+ }
+
+ if(desclpt)
+ fs_give((void **) &desclpt);
+
+ q_status_message(SM_ORDER, 0, 9, "Printing to windows printer...");
+ display_message('x');
+
+ /* init print control structure */
+ ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S));
+ memset(ps_global->print, 0, sizeof(PRINT_S));
+
+ ps_global->print->err = 0;
+#endif /* _WINDOWS */
+
+ return(0);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Close printer
+
+ If we're piping to a spooler close down the pipe and wait for the process
+to finish. If we're sending to an attached printer send the escape sequence.
+Also let the user know the result of the print
+ ----*/
+void
+close_printer(void)
+{
+#ifndef _WINDOWS
+ if(trailer){
+ if(*trailer)
+ fputs(trailer, ps_global->print->fp);
+
+ fs_give((void **)&trailer);
+ }
+
+ if(ps_global->print->fp == stdout) {
+ if(ansi_off)
+ fputs("\033[4i", stdout);
+ else
+ printf("%c", 20); /* aux off for wyse60 */
+
+ fflush(stdout);
+ if(F_OFF(F_PRESERVE_START_STOP, ps_global))
+ xonxoff_proc(0); /* turn off XON/XOFF */
+
+ crlf_proc(0); /* turn off CF->LF xlantion */
+ } else {
+ (void) close_system_pipe(&ps_global->print->pipe, NULL, pipe_callback);
+ display_output_file(ps_global->print->result, "PRINT", NULL, 1);
+ if(ps_global->print && ps_global->print->result)
+ fs_give((void **) &ps_global->print->result);
+ }
+#else /* _WINDOWS */
+ mswin_print_done();
+#endif /* _WINDOWS */
+
+ if(ps_global->print)
+ fs_give((void **) &ps_global->print);
+
+ q_status_message(SM_ASYNC, 0, 3, "Print command completed");
+ display_message('x');
+}
+
+
+/*----------------------------------------------------------------------
+ Print a single character, translate from UTF-8 to user's locale charset.
+
+ Args: c -- char to print
+ Returns: 1 on success, 0 on ps_global->print->err
+ ----*/
+int
+print_char(int c)
+{
+#ifndef _WINDOWS
+ int i, outchars;
+ unsigned char obuf[MAX(MB_LEN_MAX,32)];
+
+ if(!ps_global->print->err
+ && (outchars = utf8_to_locale(c, &cb, obuf, sizeof(obuf)))){
+ for(i = 0; i < outchars && !ps_global->print->err; i++)
+ if(putc(obuf[i], ps_global->print->fp) == EOF)
+ ps_global->print->err = 1;
+ }
+#else /* _WINDOWS */
+ if(!ps_global->print->err
+ && (ps_global->print->err = mswin_print_char_utf8(c)))
+ q_status_message1(SM_ORDER, 0, 9, "Print cancelled: %s",
+ mswin_print_error((unsigned short)ps_global->print->err));
+#endif /* _WINDOWS */
+
+ return(!ps_global->print->err);
+}
+
+
+/*----------------------------------------------------------------------
+ Send a line of text to the printer
+
+ Args: line -- Text to print
+
+ ----*/
+void
+print_text(char *line)
+{
+#ifndef _WINDOWS
+ int slen = strlen(line);
+
+ while(!ps_global->print->err && slen--)
+ if(print_char(*line++) == 0)
+ ps_global->print->err = 1;
+#else /* _WINDOWS */
+ if(!ps_global->print->err
+ && (ps_global->print->err = mswin_print_text_utf8(line)))
+ q_status_message1(SM_ORDER, 0, 9, "Print cancelled: %s",
+ mswin_print_error((unsigned short)ps_global->print->err));
+#endif /* _WINDOWS */
+}
+
+
+/*----------------------------------------------------------------------
+ printf style formatting with one arg for printer
+
+ Args: line -- The printf control string
+ a1 -- The 1st argument for printf
+ ----*/
+void
+print_text1(char *line, char *a1)
+{
+ char buf[64000];
+
+ if(!ps_global->print->err && snprintf(buf, sizeof(buf), line, a1) < 0)
+ ps_global->print->err = 1;
+ else
+ print_text(buf);
+}
diff --git a/alpine/osdep/print.h b/alpine/osdep/print.h
new file mode 100644
index 00000000..47e28eec
--- /dev/null
+++ b/alpine/osdep/print.h
@@ -0,0 +1,28 @@
+/*
+ * $Id: print.h 761 2007-10-23 22:35:18Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_PRINT_INCLUDED
+#define PINE_OSDEP_PRINT_INCLUDED
+
+
+/* exported prototypes */
+int open_printer(char *);
+void close_printer(void);
+int print_char(int);
+void print_text(char *);
+void print_text1(char *, char *);
+
+
+#endif /* PINE_OSDEP_PRINT_INCLUDED */
diff --git a/alpine/osdep/resource.h b/alpine/osdep/resource.h
new file mode 100644
index 00000000..c52b54f9
--- /dev/null
+++ b/alpine/osdep/resource.h
@@ -0,0 +1 @@
+#include "../../pico/osdep/resource.h"
diff --git a/alpine/osdep/solquota b/alpine/osdep/solquota
new file mode 100644
index 00000000..348bad2a
--- /dev/null
+++ b/alpine/osdep/solquota
@@ -0,0 +1,174 @@
+static char *device_name();
+
+#include <fcntl.h>
+#include <sys/fs/ufs_quota.h>
+
+/*
+ * define the "quotactl" function as in Solaris 1, based on ioctl().
+ * By Marc Mazuhelli <mazu@dmi.usherb.ca>
+ * The "special" parameter is any file on the file system,
+ * not the block special device name as in Solaris 1.
+ * Thanks to veronica@solution.maths.unsw.edu.au who provided
+ * the idea and the basis for this function.
+ *
+ * [ Apparently quotactl used to exist in SunOS but no longer exists in ]
+ * [ Solaris. This is an equivalent. If you are running on a system ]
+ * [ which has quotactl, comment this routine out or use sunquota. ]
+ */
+
+int
+quotactl(int cmd, char *special, uid_t uid, struct dqblk * addr)
+{
+ struct quotctl op;
+ int fd = open(special, O_RDONLY);
+
+ if (fd < 0)
+ return -1;
+
+ op.op = cmd;
+ op.uid = uid;
+ op.addr = (caddr_t) addr;
+
+ if (ioctl(fd, Q_QUOTACTL, &op) < 0) {
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return (0);
+}
+
+
+/*----------------------------------------------------------------------
+ Return space left in disk quota on file system which given path is in.
+
+ Args: path - Path name of file or directory on file system of concern
+ over - pointer to flag that is set if the user is over quota
+
+ Returns: If *over = 0, the number of bytes free in disk quota as per
+ the soft limit.
+ If *over = 1, the number of bytes *over* quota.
+ -1 is returned on an error looking up quota
+ 0 is returned if there is no quota
+
+BUG: If there's more than 2.1Gb free this function will break
+ ----*/
+long
+disk_quota(path, over)
+ char *path;
+ int *over;
+{
+ static int no_quota = 0;
+ struct stat statx;
+ struct dqblk quotax;
+ long q;
+ char *dname;
+
+ if(no_quota)
+ return(0L); /* If no quota the first time, then none the second. */
+
+ dprint(5, (debugfile, "quota_check path: %s\n", path ? path : "?"));
+ if(stat(path, &statx) < 0) {
+ return(-1L);
+ }
+
+ *over = 0;
+ errno = 0;
+
+ dname = device_name(statx.st_dev);
+ if(dname == NULL)
+ return(-1L);
+
+ dprint(7, (debugfile, "Quota check: UID:%d device: %s\n",
+ getuid(), dname ? dname : "?"));
+ if(quotactl(Q_GETQUOTA, dname, getuid(), (char *)&quotax) < 0) {
+ dprint(5, (debugfile, "Quota failed : %s\n",
+ error_description(errno)));
+ return(-1L); /* Something went wrong */
+ }
+
+ dprint(5,(debugfile,"Quota: bsoftlimit:%d bhardlimit:%d curblock:%d\n",
+ quotax.dqb_bsoftlimit, quotax.dqb_bhardlimit, quotax.dqb_curblocks));
+
+ if(quotax.dqb_bsoftlimit == -1)
+ return(-1L);
+
+ q = (quotax.dqb_bsoftlimit - quotax.dqb_curblocks) * 512;
+
+ if(q < 0) {
+ q = -q;
+ *over = 1;
+ }
+ dprint(5, (debugfile, "disk_quota returning :%d, over:%d\n", q, *over));
+ return(q);
+}
+
+
+/*----------------------------------------------------------------------
+ * devNumToName
+ *
+ * This routine is here so that ex can get a device name to check
+ * disk quotas. One might wonder, why not use getmntent(), rather
+ * than read /etc/mtab in this crude way? The problem with getmntent
+ * is that it uses stdio, and ex/vi pointedly doesn't.
+ ----*/
+static char
+*device_name(st_devArg)
+ dev_t st_devArg;
+{
+#ifndef MTABNAME
+#define MTABNAME "/etc/mtab"
+#endif
+ char *mtab;
+ static char devName[48];
+ static char *answer = (char *) 0;
+ struct stat devStat;
+ static dev_t st_dev;
+ int nb, cur, bol;
+ char c;
+ int dname;
+
+ if (st_devArg == st_dev)
+ return answer;
+
+ mtab = read_file(MTABNAME);
+ if(mtab == NULL)
+ return((char *)NULL);
+
+ /* Initialize save data. */
+ st_dev = st_devArg;
+ answer = (char *) 0;
+ nb = strlen(mtab);
+
+ for (cur=bol=0, dname=1; cur < nb; ++cur) {
+
+ if (dname && (mtab[cur] <= ' ')) {
+ /* Space, tab or other such character has been found,
+ presumably marking the end of the device name string. */
+
+ dname = 0;
+ c = mtab[cur]; /* Save current character. */
+ mtab[cur] = 0; /* C zero-terminated string. */
+
+ /* Get device number, via stat(). If it's the right
+ number, copy the string and return its address. */
+ if (stat (&mtab[bol], &devStat) == 0) {
+ if (devStat.st_rdev == st_dev) {
+ if ((cur - bol + 1) < sizeof (devName)) {
+ strncpy (devName, &mtab[bol], sizeof(devName));
+ devName[sizeof(devName)-1] = '\0';
+ answer = &devName[0];
+ return(answer);
+ }
+ }
+ }
+ mtab[cur] = c;
+ }
+ if (mtab[cur] == '\n') {
+ dname = 1;
+ bol = cur + 1;
+ }
+ }
+ answer = NULL;
+
+ return(answer);
+}
diff --git a/alpine/osdep/sunquota b/alpine/osdep/sunquota
new file mode 100644
index 00000000..3528a1bb
--- /dev/null
+++ b/alpine/osdep/sunquota
@@ -0,0 +1,136 @@
+static char *device_name();
+
+/*----------------------------------------------------------------------
+ Return space left in disk quota on file system which given path is in.
+
+ Args: path - Path name of file or directory on file system of concern
+ over - pointer to flag that is set if the user is over quota
+
+ Returns: If *over = 0, the number of bytes free in disk quota as per
+ the soft limit.
+ If *over = 1, the number of bytes *over* quota.
+ -1 is returned on an error looking up quota
+ 0 is returned if there is no quota
+
+BUG: If there's more than 2.1Gb free this function will break
+ ----*/
+long
+disk_quota(path, over)
+ char *path;
+ int *over;
+{
+ static int no_quota = 0;
+ struct stat statx;
+ struct dqblk quotax;
+ long q;
+ char *dname;
+
+ if(no_quota)
+ return(0L); /* If no quota the first time, then none the second. */
+
+ dprint(5, (debugfile, "quota_check path: %s\n", path ? path : "?"));
+ if(stat(path, &statx) < 0) {
+ return(-1L);
+ }
+
+ *over = 0;
+ errno = 0;
+
+ dname = device_name(statx.st_dev);
+ if(dname == NULL)
+ return(-1L);
+
+ dprint(7, (debugfile, "Quota check: UID:%d device: %s\n",
+ getuid(), dname ? dname : "?"));
+ if(quotactl(Q_GETQUOTA, dname, getuid(), (char *)&quotax) < 0) {
+ dprint(5, (debugfile, "Quota failed : %s\n",
+ error_description(errno)));
+ return(-1L); /* Something went wrong */
+ }
+
+ dprint(5,(debugfile,"Quota: bsoftlimit:%d bhardlimit:%d curblock:%d\n",
+ quotax.dqb_bsoftlimit, quotax.dqb_bhardlimit, quotax.dqb_curblocks));
+
+ if(quotax.dqb_bsoftlimit == -1)
+ return(-1L);
+
+ q = (quotax.dqb_bsoftlimit - quotax.dqb_curblocks) * 512;
+
+ if(q < 0) {
+ q = -q;
+ *over = 1;
+ }
+ dprint(5, (debugfile, "disk_quota returning :%d, over:%d\n", q, *over));
+ return(q);
+}
+
+
+/*----------------------------------------------------------------------
+ * devNumToName
+ *
+ * This routine is here so that ex can get a device name to check
+ * disk quotas. One might wonder, why not use getmntent(), rather
+ * than read /etc/mtab in this crude way? The problem with getmntent
+ * is that it uses stdio, and ex/vi pointedly doesn't.
+ ----*/
+static char
+*device_name(st_devArg)
+ dev_t st_devArg;
+{
+#ifndef MTABNAME
+#define MTABNAME "/etc/mtab"
+#endif
+ char *mtab;
+ static char devName[48];
+ static char *answer = (char *) 0;
+ struct stat devStat;
+ static dev_t st_dev;
+ int nb, cur, bol;
+ char c;
+ int dname;
+
+ if (st_devArg == st_dev)
+ return answer;
+
+ mtab = read_file(MTABNAME);
+ if(mtab == NULL)
+ return((char *)NULL);
+
+ /* Initialize save data. */
+ st_dev = st_devArg;
+ answer = (char *) 0;
+ nb = strlen(mtab);
+
+ for (cur=bol=0, dname=1; cur < nb; ++cur) {
+
+ if (dname && (mtab[cur] <= ' ')) {
+ /* Space, tab or other such character has been found,
+ presumably marking the end of the device name string. */
+
+ dname = 0;
+ c = mtab[cur]; /* Save current character. */
+ mtab[cur] = 0; /* C zero-terminated string. */
+
+ /* Get device number, via stat(). If it's the right
+ number, copy the string and return its address. */
+ if (stat (&mtab[bol], &devStat) == 0) {
+ if (devStat.st_rdev == st_dev) {
+ if ((cur - bol + 1) < sizeof (devName)) {
+ strncpy (devName, &mtab[bol], sizeof(devName));
+ devName[sizeof(devName)-1] = '\0';
+ answer = &devName[0];
+ return(answer);
+ }
+ }
+ }
+ mtab[cur] = c;
+ }
+ if (mtab[cur] == '\n') {
+ dname = 1;
+ bol = cur + 1;
+ }
+ }
+ answer = NULL;
+
+ return(answer);
+}
diff --git a/alpine/osdep/termin.gen.c b/alpine/osdep/termin.gen.c
new file mode 100644
index 00000000..fb106be1
--- /dev/null
+++ b/alpine/osdep/termin.gen.c
@@ -0,0 +1,1252 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: termin.gen.c 1025 2008-04-08 22:59:38Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2008 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+#include <system.h>
+#include <general.h>
+
+#include "../../c-client/mail.h" /* for MAILSTREAM and friends */
+#include "../../c-client/osdep.h"
+#include "../../c-client/rfc822.h" /* for soutr_t and such */
+#include "../../c-client/misc.h" /* for cpystr proto */
+#include "../../c-client/utf8.h" /* for CHARSET and such*/
+#include "../../c-client/imap4r1.h"
+
+#include "../../pith/osdep/color.h"
+
+#include "../../pith/charconv/utf8.h"
+
+#include "../../pith/debug.h"
+#include "../../pith/newmail.h"
+#include "../../pith/conf.h"
+#include "../../pith/busy.h"
+
+#include "../../pico/estruct.h"
+#include "../../pico/pico.h"
+#include "../../pico/keydefs.h"
+
+#include "../../pico/osdep/color.h"
+
+#include "../status.h"
+#include "../folder.h"
+#include "../keymenu.h"
+#include "../send.h"
+#include "../radio.h"
+#include "../busy.h"
+
+#ifdef _WINDOWS
+#include "../../pico/osdep/mswin.h"
+#include "termin.wnt.h"
+#include "termout.wnt.h"
+#else
+#include "termout.unx.h"
+#endif
+
+#include "termin.gen.h"
+#include "termout.gen.h"
+
+#include "../mailcmd.h"
+
+
+#ifdef _WINDOWS
+static int g_mc_row, g_mc_col;
+
+int pcpine_oe_cursor(int, long);
+#endif
+
+
+/*
+ * Generic tty input routines
+ */
+
+
+/*----------------------------------------------------------------------
+ Read a character from keyboard with timeout
+ Input: none
+
+ Result: Returns command read via read_char
+ Times out and returns a null command every so often
+
+ Calculates the timeout for the read, and does a few other house keeping
+things. The duration of the timeout is set in pine.c.
+ ----------------------------------------------------------------------*/
+UCS
+read_command(char **utf8str)
+{
+ int tm = 0, more_freq_timeo;
+ UCS ucs;
+ long dtime;
+ static unsigned char utf8buf[7];
+ unsigned char *newdestp;
+
+ /*
+ * timeo is the mail-check-interval. What we want to do (ignoring the
+ * messages_queued part) is timeout more often than timeo but only
+ * check for new mail every timeo or so seconds. The reason we want to
+ * timeout more often is so that we will have a chance to catch the user
+ * in an idle period where we can do a check_point(). Otherwise, with
+ * a default mail-check-interval, we are almost always calling newmail
+ * right after the user presses a key, making it the worst possible
+ * time to do a checkpoint.
+ */
+
+ more_freq_timeo = MIN(get_input_timeout(), IDLE_TIMEOUT);
+ if(more_freq_timeo == 0)
+ more_freq_timeo = IDLE_TIMEOUT;
+
+ cancel_busy_cue(-1);
+ tm = (messages_queued(&dtime) > 1) ? (int)dtime : more_freq_timeo;
+
+ if(utf8str)
+ *utf8str = NULL;
+
+ ucs = read_char(tm);
+ if(ucs != NO_OP_COMMAND && ucs != NO_OP_IDLE && ucs != KEY_RESIZE)
+ zero_new_mail_count();
+
+#ifdef BACKGROUND_POST
+ /*
+ * Any expired children to report on?
+ */
+ if(ps_global->post && ps_global->post->pid == 0){
+ int winner = 0;
+
+ if(ps_global->post->status < 0){
+ q_status_message(SM_ORDER | SM_DING, 3, 3, "Abysmal failure!");
+ }
+ else{
+ (void) pine_send_status(ps_global->post->status,
+ ps_global->post->fcc, tmp_20k_buf, SIZEOF_20KBUF,
+ &winner);
+ q_status_message(SM_ORDER | (winner ? 0 : SM_DING), 3, 3,
+ tmp_20k_buf);
+
+ }
+
+ if(!winner)
+ q_status_message(SM_ORDER, 0, 3,
+ "Re-send via \"Compose\" then \"Yes\" to \"Continue INTERRUPTED?\"");
+
+ if(ps_global->post->fcc)
+ fs_give((void **) &ps_global->post->fcc);
+
+ fs_give((void **) &ps_global->post);
+ }
+#endif
+
+ /*
+ * The character we get from read_char() is a UCS-4 char. Or it could be a special
+ * value like KEY_UP or NO_OP_IDLE or something similar. From here on out
+ * we're going to operate with UTF-8 internally. This is the point where we
+ * convert the UCS-4 input (actually whatever sort of input the user is typing
+ * was converted to UCS-4 first) to UTF-8. It's easy in this read_command
+ * case because if user types a non-ascii character as a command it's going to be
+ * an error. All commands are ascii. In order to present a reasonable error
+ * message we pass back the UTF-8 string to the caller.
+ */
+ if(ucs >= 0x80 && ucs < KEY_BASE){
+ /*
+ * User typed a character that is non-ascii. Convert it to
+ * UTF-8.
+ */
+ memset(utf8buf, 0, sizeof(utf8buf));
+ newdestp = utf8_put(utf8buf, (unsigned long) ucs);
+ if(newdestp - utf8buf > 1){ /* this should happen */
+ if(utf8str)
+ *utf8str = (char *) utf8buf;
+
+ dprint((9, "Read command: looks like user typed non-ascii command 0x%x %s: returning KEY_UTF8\n", ucs, pretty_command(ucs)));
+ ucs = KEY_UTF8;
+ }
+ else{
+ dprint((9, "Read command: looks like user typed unknown, non-ascii command 0x%x %s: returning KEY_UNKNOWN\n", ucs, pretty_command(ucs)));
+ ucs = KEY_UNKNOWN; /* best we can do, shouldn't happen */
+ }
+ }
+ else{
+ dprint((9, "Read command returning: 0x%x %s\n", ucs, pretty_command(ucs)));
+ }
+
+ return(ucs);
+}
+
+
+int
+read_command_prep()
+{
+ int i;
+ char *fname;
+ MAILSTREAM *m;
+
+ /*
+ * Before we sniff at the input queue, make sure no external event's
+ * changed our picture of the message sequence mapping. If so,
+ * recalculate the dang thing and run thru whatever processing loop
+ * we're in again...
+ */
+ for(i = 0; i < ps_global->s_pool.nstream; i++){
+ m = ps_global->s_pool.streams[i];
+ if(m && sp_flagged(m, SP_LOCKED) && sp_flagged(m, SP_USERFLDR)
+ && sp_expunge_count(m)){
+ fname = STREAMNAME(m);
+ q_status_message3(SM_ORDER, 3, 3,
+ "%s message%s expunged from folder \"%s\"",
+ long2string(sp_expunge_count(m)),
+ plural(sp_expunge_count(m)),
+ pretty_fn(fname));
+ sp_set_expunge_count(m, 0L);
+ display_message('x');
+ }
+ }
+
+ if(sp_mail_box_changed(ps_global->mail_stream)
+ && sp_new_mail_count(ps_global->mail_stream)){
+ dprint((2, "Noticed %ld new msgs! \n",
+ sp_new_mail_count(ps_global->mail_stream)));
+ return(FALSE); /* cycle thru so caller can update */
+ }
+
+ return(TRUE);
+}
+
+
+/*----------------------------------------------------------------------
+ Prompt user for a string in status line with various options
+
+ Args: utf8string -- the buffer result is returned in, and original string (if
+ any) is passed in.
+ y_base -- y position on screen to start on. 0,0 is upper left
+ negative numbers start from bottom
+ x_base -- column position on screen to start on. 0,0 is upper left
+ utf8string_size -- Length of utf8string buffer
+ utf8prompt -- The string to prompt with
+ escape_list -- pointer to array of ESCKEY_S's. input chars matching
+ those in list return value from list.
+ help -- Array of strings for help text in bottom screen lines
+ flags -- pointer (because some are return values) to flags
+ OE_USER_MODIFIED - Set on return if user modified buffer
+ OE_DISALLOW_CANCEL - No cancel in menu.
+ OE_DISALLOW_HELP - No help in menu.
+ OE_KEEP_TRAILING_SPACE - Allow trailing space.
+ OE_SEQ_SENSITIVE - Caller is sensitive to sequence
+ number changes.
+ OE_APPEND_CURRENT - String should not be truncated
+ before accepting user input.
+ OE_PASSWD - Don't echo on screen.
+
+ Result: editing input string
+ returns -1 unexpected errors
+ returns 0 normal entry typed (editing and return or PF2)
+ returns 1 typed ^C or PF2 (cancel)
+ returns 3 typed ^G or PF1 (help)
+ returns 4 typed ^L for a screen redraw
+
+ WARNING: Care is required with regard to the escape_list processing.
+ The passed array is terminated with an entry that has ch = -1.
+ Function key labels and key strokes need to be setup externally!
+ Traditionally, a return value of 2 is used for ^T escapes.
+
+ Unless in escape_list, tabs are trapped by isprint().
+This allows near full weemacs style editing in the line
+ ^A beginning of line
+ ^E End of line
+ ^R Redraw line
+ ^G Help
+ ^F forward
+ ^B backward
+ ^D delete
+----------------------------------------------------------------------*/
+
+int
+optionally_enter(char *utf8string, int y_base, int x_base, int utf8string_size,
+ char *utf8prompt, ESCKEY_S *escape_list, HelpType help, int *flags)
+{
+ UCS *string = NULL, ucs;
+ size_t string_size;
+ UCS *s2;
+ UCS *saved_original = NULL;
+ char *candidate;
+ UCS *kill_buffer = NULL;
+ UCS *k, *kb;
+ int field_pos; /* offset into array dline.vl */
+ int i, j, return_v, cols, prompt_width, too_thin,
+ real_y_base, km_popped, passwd;
+ char **help_text;
+ long fkey_table[12];
+ struct key_menu *km;
+ bitmap_t bitmap;
+ COLOR_PAIR *lastc = NULL, *promptc = NULL;
+ struct variable *vars = ps_global->vars;
+ struct display_line dline;
+#ifdef _WINDOWS
+ int cursor_shown;
+#endif
+
+ dprint((5, "=== optionally_enter called ===\n"));
+ dprint((9, "utf8string:\"%s\" y:%d x:%d length: %d append: %d\n",
+ utf8string ? utf8string : "",
+ x_base, y_base, utf8string_size,
+ (flags && *flags & OE_APPEND_CURRENT)));
+ dprint((9, "passwd:%d utf8prompt:\"%s\" label:\"%s\"\n",
+ (flags && *flags & OE_PASSWD_NOAST) ? 10 :
+ (flags && *flags & OE_PASSWD) ? 1 : 0,
+ utf8prompt ? utf8prompt : "",
+ (escape_list && escape_list[0].ch != -1 && escape_list[0].label)
+ ? escape_list[0].label: ""));
+
+ if(!ps_global->ttyo)
+ return(pre_screen_config_opt_enter(utf8string, utf8string_size, utf8prompt,
+ escape_list, help, flags));
+
+#ifdef _WINDOWS
+ if (mswin_usedialog ())
+ return(win_dialog_opt_enter(utf8string, utf8string_size, utf8prompt,
+ escape_list, help, flags));
+#endif
+
+
+ /*
+ * Utf8string comes in as UTF-8. We'll convert it to a UCS-4 array and operate on
+ * that array, then convert it back before returning. Utf8string_size is the size
+ * of the utf8string array but that doesn't help us much for the array we need to
+ * operate on here. We'll just allocate a big array and then cut it off when
+ * sending it back.
+ *
+ * This should come before the specialized calls above but those aren't
+ * converted to use UCS-4 yet.
+ */
+ string = utf8_to_ucs4_cpystr(utf8string);
+ dline.vused = ucs4_strlen(string);
+
+ string_size = (2 * MAX(utf8string_size,dline.vused) + 100);
+ fs_resize((void **) &string, string_size * sizeof(UCS));
+
+ suspend_busy_cue();
+ cols = ps_global->ttyo->screen_cols;
+ prompt_width = utf8_width(utf8prompt);
+ too_thin = 0;
+ km_popped = 0;
+ if(y_base > 0)
+ real_y_base = y_base;
+ else{
+ real_y_base = y_base + ps_global->ttyo->screen_rows;
+ real_y_base = MAX(real_y_base, 0);
+ }
+
+ flush_ordered_messages();
+ mark_status_dirty();
+
+ if(flags && *flags & OE_APPEND_CURRENT) /* save a copy in case of cancel */
+ saved_original = ucs4_cpystr(string);
+
+ /*
+ * build the function key mapping table, skipping predefined keys...
+ */
+ memset(fkey_table, NO_OP_COMMAND, 12 * sizeof(long));
+ for(i = 0, j = 0; escape_list && escape_list[i].ch != -1 && i+j < 12; i++){
+ if(i+j == OE_HELP_KEY)
+ j++;
+
+ if(i+j == OE_CANCEL_KEY)
+ j++;
+
+ if(i+j == OE_ENTER_KEY)
+ j++;
+
+ fkey_table[i+j] = escape_list[i].ch;
+ }
+
+ /* assumption that HelpType is char ** */
+ help_text = help;
+ if(help_text){ /*---- Show help text -----*/
+ int width = ps_global->ttyo->screen_cols - x_base;
+
+ if(FOOTER_ROWS(ps_global) == 1){
+ km_popped++;
+ FOOTER_ROWS(ps_global) = 3;
+ clearfooter(ps_global);
+
+ y_base = -3;
+ real_y_base = y_base + ps_global->ttyo->screen_rows;
+ }
+
+ for(j = 0; j < 2 && help_text[j]; j++){
+ MoveCursor(real_y_base + 1 + j, x_base);
+ CleartoEOLN();
+
+ if(width < utf8_width(help_text[j])){
+ char *tmp = cpystr(help_text[j]);
+ (void) utf8_truncate(tmp, width);
+ PutLine0(real_y_base + 1 + j, x_base, tmp);
+ fs_give((void **) &tmp);
+ }
+ else
+ PutLine0(real_y_base + 1 + j, x_base, help_text[j]);
+ }
+ }
+ else{
+ clrbitmap(bitmap);
+ clrbitmap((km = &oe_keymenu)->bitmap); /* force formatting */
+ if(!(flags && (*flags) & OE_DISALLOW_HELP))
+ setbitn(OE_HELP_KEY, bitmap);
+
+ setbitn(OE_ENTER_KEY, bitmap);
+ if(!(flags && (*flags) & OE_DISALLOW_CANCEL))
+ setbitn(OE_CANCEL_KEY, bitmap);
+
+ setbitn(OE_CTRL_T_KEY, bitmap);
+
+ /*---- Show the usual possible keys ----*/
+ for(i=0,j=0; escape_list && escape_list[i].ch != -1 && i+j < 12; i++){
+ if(i+j == OE_HELP_KEY)
+ j++;
+
+ if(i+j == OE_CANCEL_KEY)
+ j++;
+
+ if(i+j == OE_ENTER_KEY)
+ j++;
+
+ oe_keymenu.keys[i+j].label = escape_list[i].label;
+ oe_keymenu.keys[i+j].name = escape_list[i].name;
+ setbitn(i+j, bitmap);
+ }
+
+ for(i = i+j; i < 12; i++)
+ if(!(i == OE_HELP_KEY || i == OE_ENTER_KEY || i == OE_CANCEL_KEY))
+ oe_keymenu.keys[i].name = NULL;
+
+ draw_keymenu(km, bitmap, cols, 1-FOOTER_ROWS(ps_global), 0, FirstMenu);
+ }
+
+ if(pico_usingcolor() && VAR_PROMPT_FORE_COLOR &&
+ VAR_PROMPT_BACK_COLOR &&
+ pico_is_good_color(VAR_PROMPT_FORE_COLOR) &&
+ pico_is_good_color(VAR_PROMPT_BACK_COLOR)){
+ lastc = pico_get_cur_color();
+ if(lastc){
+ promptc = new_color_pair(VAR_PROMPT_FORE_COLOR,
+ VAR_PROMPT_BACK_COLOR);
+ (void)pico_set_colorp(promptc, PSC_NONE);
+ }
+ }
+ else
+ StartInverse();
+
+ /*
+ * if display length isn't wide enough to support input,
+ * shorten up the prompt...
+ */
+ if((dline.dwid = cols - (x_base + prompt_width)) < MIN_OPT_ENT_WIDTH){
+ char *p;
+ unsigned got_width;
+
+ /*
+ * Scoot prompt pointer forward at least (MIN_OPT_ENT_WIDTH - dline.dwid) screencells.
+ */
+ p = utf8_count_forw_width(utf8prompt, MIN_OPT_ENT_WIDTH-dline.dwid, &got_width);
+ if(got_width < MIN_OPT_ENT_WIDTH-dline.dwid)
+ p = utf8_count_forw_width(utf8prompt, MIN_OPT_ENT_WIDTH+1-dline.dwid, &got_width);
+
+ if(p){
+ prompt_width = utf8_width(p);
+ dline.dwid = cols - (x_base + prompt_width);
+ utf8prompt = p;
+ }
+ }
+
+ /*
+ * How many UCS-4 characters will we need to make up the width dwid? It could be
+ * unlimited because of zero-width characters, I suppose, but realistically it
+ * isn't going to be much more than dwid.
+ */
+ dline.dlen = 2 * dline.dwid + 100;
+
+ dline.dl = (UCS *) fs_get(dline.dlen * sizeof(UCS));
+ dline.olddl = (UCS *) fs_get(dline.dlen * sizeof(UCS));
+ memset(dline.dl, 0, dline.dlen * sizeof(UCS));
+ memset(dline.olddl, 0, dline.dlen * sizeof(UCS));
+
+ dline.movecursor = MoveCursor;
+ dline.writechar = Writewchar;
+
+ dline.row = real_y_base;
+ dline.col = x_base + prompt_width;
+
+ dline.vl = string;
+ dline.vlen = --string_size; /* -1 for terminating zero */
+ dline.vbase = field_pos = 0;
+
+#ifdef _WINDOWS
+ cursor_shown = mswin_showcaret(1);
+#endif
+
+ PutLine0(real_y_base, x_base, utf8prompt);
+
+ /*
+ * If appending, position field_pos at end of input.
+ */
+ if(flags && *flags & OE_APPEND_CURRENT)
+ while(string[field_pos])
+ field_pos++;
+
+ passwd = (flags && *flags & OE_PASSWD_NOAST) ? 10 :
+ (flags && *flags & OE_PASSWD) ? 1 : 0;
+ line_paint(field_pos, &dline, &passwd);
+
+ /*----------------------------------------------------------------------
+ The main loop
+ loops until someone sets the return_v.
+ ----------------------------------------------------------------------*/
+ return_v = -10;
+
+ while(return_v == -10) {
+
+#ifdef MOUSE
+ mouse_in_content(KEY_MOUSE, -1, -1, 0x5, 0);
+ register_mfunc(mouse_in_content,
+ real_y_base, x_base + prompt_width,
+ real_y_base, ps_global->ttyo->screen_cols);
+#endif
+#ifdef _WINDOWS
+ mswin_allowpaste(MSWIN_PASTE_LINE);
+ g_mc_row = real_y_base;
+ g_mc_col = x_base + prompt_width;
+ mswin_mousetrackcallback(pcpine_oe_cursor);
+#endif
+
+ /* Timeout 10 min to keep imap mail stream alive */
+ ps_global->conceal_sensitive_debugging = passwd ? 1 : 0;
+ ucs = read_char(600);
+ ps_global->conceal_sensitive_debugging = 0;
+
+#ifdef MOUSE
+ clear_mfunc(mouse_in_content);
+#endif
+#ifdef _WINDOWS
+ mswin_allowpaste(MSWIN_PASTE_DISABLE);
+ mswin_mousetrackcallback(NULL);
+#endif
+
+ /*
+ * Don't want to intercept all characters if typing in passwd.
+ * We select an ad hoc set that we will catch and let the rest
+ * through. We would have caught the set below in the big switch
+ * but we skip the switch instead. Still catch things like ^K,
+ * DELETE, ^C, RETURN.
+ */
+ if(passwd)
+ switch(ucs){
+ case ctrl('F'):
+ case KEY_RIGHT:
+ case ctrl('B'):
+ case KEY_LEFT:
+ case ctrl('U'):
+ case ctrl('A'):
+ case KEY_HOME:
+ case ctrl('E'):
+ case KEY_END:
+ case TAB:
+ goto ok_for_passwd;
+ }
+
+ if(too_thin && ucs != KEY_RESIZE && ucs != ctrl('Z') && ucs != ctrl('C'))
+ goto bleep;
+
+ switch(ucs){
+
+ /*--------------- KEY RIGHT ---------------*/
+ case ctrl('F'):
+ case KEY_RIGHT:
+ if(field_pos >= string_size || string[field_pos] == '\0')
+ goto bleep;
+
+ line_paint(++field_pos, &dline, &passwd);
+ break;
+
+ /*--------------- KEY LEFT ---------------*/
+ case ctrl('B'):
+ case KEY_LEFT:
+ if(field_pos <= 0)
+ goto bleep;
+
+ line_paint(--field_pos, &dline, &passwd);
+ break;
+
+ /*-------------------- WORD SKIP --------------------*/
+ case ctrl('@'):
+ /*
+ * Note: read_char *can* return NO_OP_COMMAND which is
+ * the def'd with the same value as ^@ (NULL), BUT since
+ * read_char has a big timeout (>25 secs) it won't.
+ */
+
+ /* skip thru current word */
+ while(string[field_pos]
+ && isalnum((unsigned char) string[field_pos]))
+ field_pos++;
+
+ /* skip thru current white space to next word */
+ while(string[field_pos]
+ && !isalnum((unsigned char) string[field_pos]))
+ field_pos++;
+
+ line_paint(field_pos, &dline, &passwd);
+ break;
+
+ /*-------------------- RETURN --------------------*/
+ case PF4:
+ if(F_OFF(F_USE_FK,ps_global)) goto bleep;
+ case ctrl('J'):
+ case ctrl('M'):
+ return_v = 0;
+ break;
+
+ /*-------------------- Destructive backspace --------------------*/
+ case '\177': /* DEL */
+ case ctrl('H'):
+ /* Try and do this with by telling the terminal to delete a
+ a character. If that fails, then repaint the rest of the
+ line, acheiving the same much less efficiently
+ */
+ if(field_pos <= 0)
+ goto bleep;
+
+ field_pos--;
+ /* drop thru to pull line back ... */
+
+ /*-------------------- Delete char --------------------*/
+ case ctrl('D'):
+ case KEY_DEL:
+ if(field_pos >= string_size || !string[field_pos])
+ goto bleep;
+
+ dline.vused--;
+ for(s2 = &string[field_pos]; *s2 != 0; s2++)
+ *s2 = s2[1];
+
+ *s2 = 0; /* Copy last NULL */
+ line_paint(field_pos, &dline, &passwd);
+ if(flags) /* record change if requested */
+ *flags |= OE_USER_MODIFIED;
+
+ break;
+
+ /*--------------- Kill line -----------------*/
+ case ctrl('K'):
+ if(kill_buffer != NULL)
+ fs_give((void **) &kill_buffer);
+
+ if(field_pos != 0 || string[0]){
+ if(!passwd && F_ON(F_DEL_FROM_DOT, ps_global))
+ dline.vused -= ucs4_strlen(&string[i = field_pos]);
+ else
+ dline.vused = i = 0;
+
+ kill_buffer = ucs4_cpystr(&string[field_pos = i]);
+ string[field_pos] = '\0';
+ line_paint(field_pos, &dline, &passwd);
+ if(flags) /* record change if requested */
+ *flags |= OE_USER_MODIFIED;
+ }
+
+ break;
+
+ /*------------------- Undelete line --------------------*/
+ case ctrl('U'):
+ if(kill_buffer == NULL)
+ goto bleep;
+
+ /* Make string so it will fit */
+ kb = ucs4_cpystr(kill_buffer);
+ if(ucs4_strlen(kb) + ucs4_strlen(string) > string_size)
+ kb[string_size - ucs4_strlen(string)] = '\0';
+
+ if(string[field_pos] == '\0') {
+ /*--- adding to the end of the string ----*/
+ for(k = kb; *k; k++)
+ string[field_pos++] = *k;
+
+ string[field_pos] = '\0';
+ }
+ else{
+ int shift;
+
+ shift = ucs4_strlen(kb);
+
+ /* shift field_pos ... end to right */
+ for(k = &string[field_pos] + ucs4_strlen(&string[field_pos]);
+ k >= &string[field_pos]; k--)
+ *(k+shift) = *k;
+
+ for(k = kb; *k; k++)
+ string[field_pos++] = *k;
+ }
+
+ if(*kb && flags) /* record change if requested */
+ *flags |= OE_USER_MODIFIED;
+
+ dline.vused = ucs4_strlen(string);
+ fs_give((void **) &kb);
+ line_paint(field_pos, &dline, &passwd);
+ break;
+
+ /*-------------------- Interrupt --------------------*/
+ case ctrl('C'): /* ^C */
+ if(F_ON(F_USE_FK,ps_global) || (flags && ((*flags) & OE_DISALLOW_CANCEL)))
+ goto bleep;
+
+ goto cancel;
+
+ case PF2:
+ if(F_OFF(F_USE_FK,ps_global) || (flags && ((*flags) & OE_DISALLOW_CANCEL)))
+ goto bleep;
+
+ cancel:
+ return_v = 1;
+ if(saved_original){
+ for(i = 0; saved_original[i]; i++)
+ string[i] = saved_original[i];
+
+ string[i] = 0;
+ }
+
+ break;
+
+ case ctrl('A'):
+ case KEY_HOME:
+ /*-------------------- Start of line -------------*/
+ line_paint(field_pos = 0, &dline, &passwd);
+ break;
+
+ case ctrl('E'):
+ case KEY_END:
+ /*-------------------- End of line ---------------*/
+ line_paint(field_pos = dline.vused, &dline, &passwd);
+ break;
+
+ /*-------------------- Help --------------------*/
+ case ctrl('G') :
+ case PF1:
+ if(flags && ((*flags) & OE_DISALLOW_HELP))
+ goto bleep;
+ else if(FOOTER_ROWS(ps_global) == 1 && km_popped == 0){
+ km_popped++;
+ FOOTER_ROWS(ps_global) = 3;
+ clearfooter(ps_global);
+ if(lastc)
+ (void)pico_set_colorp(lastc, PSC_NONE);
+ else
+ EndInverse();
+
+ draw_keymenu(km, bitmap, cols, 1-FOOTER_ROWS(ps_global),
+ 0, FirstMenu);
+
+ if(promptc)
+ (void)pico_set_colorp(promptc, PSC_NONE);
+ else
+ StartInverse();
+
+ mark_keymenu_dirty();
+ y_base = -3;
+ dline.row = real_y_base = y_base + ps_global->ttyo->screen_rows;
+ PutLine0(real_y_base, x_base, utf8prompt);
+ memset(dline.dl, 0, dline.dlen * sizeof(UCS));
+ memset(dline.olddl, 0, dline.dlen * sizeof(UCS));
+ line_paint(field_pos, &dline, &passwd);
+ break;
+ }
+
+ if(FOOTER_ROWS(ps_global) > 1){
+ mark_keymenu_dirty();
+ return_v = 3;
+ }
+ else
+ goto bleep;
+
+ break;
+
+
+#ifdef MOUSE
+ /* Mouse support untested in pine 5.00 */
+ case KEY_MOUSE :
+ {
+ MOUSEPRESS mp;
+ int w;
+
+ mouse_get_last (NULL, &mp);
+
+ switch(mp.button){
+ case M_BUTTON_LEFT : /* position cursor */
+ mp.col -= dline.col;
+
+ /*
+ * We have to figure out which character is under the cursor.
+ * This is complicated by the fact that characters may
+ * be other than one cell wide.
+ */
+
+ /* the -1 is for the '<' when text is offscreen left */
+ w = (dline.vbase > 0) ? mp.col-1 : mp.col;
+
+ if(mp.col <= 0)
+ field_pos = dline.vbase - 1;
+ else{
+ if(dline.vused <= dline.vbase
+ || ucs4_str_width_a_to_b(dline.vl,dline.vbase,dline.vused-1) <= w)
+ field_pos = dline.vused;
+ else{
+ /*
+ * Find index of 1st character that causes the
+ * width to be > w.
+ */
+ for(i = 0;
+ ucs4_str_width_a_to_b(dline.vl,dline.vbase,dline.vbase+i) <= w;
+ i++)
+ ;
+
+ field_pos = dline.vbase + i;
+ }
+ }
+
+ field_pos = MIN(MAX(field_pos, 0), dline.vused);
+
+ /* just allow line_paint to choose vbase */
+ line_paint(field_pos, &dline, &passwd);
+ break;
+
+ case M_BUTTON_RIGHT :
+#ifdef _WINDOWS
+
+ /*
+ * Same as M_BUTTON_LEFT except we paste in text after
+ * moving the cursor.
+ */
+
+ mp.col -= dline.col;
+
+ /* the -1 is for the '<' when text is offscreen left */
+ w = (dline.vbase > 0) ? mp.col-1 : mp.col;
+
+ if(mp.col <= 0)
+ field_pos = dline.vbase - 1;
+ else{
+ if(dline.vused <= dline.vbase
+ || ucs4_str_width_a_to_b(dline.vl,dline.vbase,dline.vused-1) <= w)
+ field_pos = dline.vused;
+ else{
+ /*
+ * Find index of 1st character that causes the
+ * width to be > w.
+ */
+ for(i = 0;
+ ucs4_str_width_a_to_b(dline.vl,dline.vbase,dline.vbase+i) <= w;
+ i++)
+ ;
+
+ field_pos = dline.vbase + i;
+ }
+ }
+
+ field_pos = MIN(MAX(field_pos, 0), dline.vused);
+
+ line_paint(field_pos, &dline, &passwd);
+
+ mswin_allowpaste(MSWIN_PASTE_LINE);
+ mswin_paste_popup();
+ mswin_allowpaste(MSWIN_PASTE_DISABLE);
+ break;
+#endif
+
+ case M_BUTTON_MIDDLE : /* NO-OP for now */
+ default: /* just ignore */
+ break;
+ }
+ }
+
+ break;
+#endif
+
+
+ case NO_OP_IDLE:
+ /*
+ * Keep mail stream alive by checking for new mail.
+ * If we're asking for a password in a login prompt
+ * we don't want to check for new_mail because the
+ * new mail check might be what got us here in the first
+ * place (because of a filter trying to save a message).
+ * If we need to wait for the user to come back then
+ * the caller will just have to deal with the failure
+ * to login.
+ */
+ i = -1;
+ if(!ps_global->no_newmail_check_from_optionally_enter)
+ i = new_mail(0, 2, NM_DEFER_SORT);
+
+ if(sp_expunge_count(ps_global->mail_stream) &&
+ flags && ((*flags) & OE_SEQ_SENSITIVE))
+ goto cancel;
+
+ if(i < 0){
+ line_paint(field_pos, &dline, &passwd);
+ break; /* no changes, get on with life */
+ }
+ /* Else fall into redraw */
+
+ /*-------------------- Redraw --------------------*/
+ case ctrl('L'):
+ /*---------------- re size ----------------*/
+ case KEY_RESIZE:
+
+ dline.row = real_y_base = y_base > 0 ? y_base :
+ y_base + ps_global->ttyo->screen_rows;
+ if(lastc)
+ (void)pico_set_colorp(lastc, PSC_NONE);
+ else
+ EndInverse();
+
+ ClearScreen();
+ redraw_titlebar();
+ if(ps_global->redrawer != (void (*)(void))NULL)
+ (*ps_global->redrawer)();
+
+ redraw_keymenu();
+ if(promptc)
+ (void)pico_set_colorp(promptc, PSC_NONE);
+ else
+ StartInverse();
+
+ PutLine0(real_y_base, x_base, utf8prompt);
+ cols = ps_global->ttyo->screen_cols;
+ too_thin = 0;
+ if(cols < x_base + prompt_width + 4){
+ Writechar(BELL, 0);
+ PutLine0(real_y_base, 0, "Screen's too thin. Ouch!");
+ too_thin = 1;
+ }
+ else{
+ dline.col = x_base + prompt_width;
+ dline.dwid = cols - (x_base + prompt_width);
+ dline.dlen = 2 * dline.dwid + 100;
+ fs_resize((void **) &dline.dl, (size_t) dline.dlen * sizeof(UCS));
+ fs_resize((void **) &dline.olddl, (size_t) dline.dlen * sizeof(UCS));
+ memset(dline.dl, 0, dline.dlen * sizeof(UCS));
+ memset(dline.olddl, 0, dline.dlen * sizeof(UCS));
+ line_paint(field_pos, &dline, &passwd);
+ }
+
+ fflush(stdout);
+
+ dprint((9,
+ "optionally_enter RESIZE new_cols:%d too_thin: %d\n",
+ cols, too_thin));
+ break;
+
+ case PF3 : /* input to potentially remap */
+ case PF5 :
+ case PF6 :
+ case PF7 :
+ case PF8 :
+ case PF9 :
+ case PF10 :
+ case PF11 :
+ case PF12 :
+ if(F_ON(F_USE_FK,ps_global)
+ && fkey_table[ucs - PF1] != NO_OP_COMMAND)
+ ucs = fkey_table[ucs - PF1]; /* remap function key input */
+
+ default:
+ if(escape_list){ /* in the escape key list? */
+ for(j=0; escape_list[j].ch != -1; j++){
+ if(escape_list[j].ch == ucs){
+ return_v = escape_list[j].rval;
+ break;
+ }
+ }
+
+ if(return_v != -10)
+ break;
+ }
+
+ if(ucs < 0x80 && FILTER_THIS((unsigned char) ucs)){
+ bleep:
+ putc(BELL, stdout);
+ continue;
+ }
+
+ ok_for_passwd:
+ /*--- Insert a character -----*/
+ if(dline.vused >= string_size)
+ goto bleep;
+
+ /*---- extending the length of the string ---*/
+ for(s2 = &string[++dline.vused]; s2 - string > field_pos; s2--)
+ *s2 = *(s2-1);
+
+ string[field_pos++] = ucs;
+ line_paint(field_pos, &dline, &passwd);
+ if(flags) /* record change if requested */
+ *flags |= OE_USER_MODIFIED;
+
+ } /*---- End of switch on char ----*/
+ }
+
+#ifdef _WINDOWS
+ if(!cursor_shown)
+ mswin_showcaret(0);
+#endif
+
+ if(dline.dl)
+ fs_give((void **) &dline.dl);
+
+ if(dline.olddl)
+ fs_give((void **) &dline.olddl);
+
+ if(saved_original)
+ fs_give((void **) &saved_original);
+
+ if(kill_buffer)
+ fs_give((void **) &kill_buffer);
+
+ /*
+ * Change string back into UTF-8.
+ */
+ candidate = ucs4_to_utf8_cpystr(string);
+
+ if(string)
+ fs_give((void **) &string);
+
+ if(candidate){
+ strncpy(utf8string, candidate, utf8string_size);
+ utf8string[utf8string_size-1] = '\0';
+ fs_give((void **) &candidate);
+ }
+
+ if (!(flags && (*flags) & OE_KEEP_TRAILING_SPACE))
+ removing_trailing_white_space(utf8string);
+
+ if(lastc){
+ (void)pico_set_colorp(lastc, PSC_NONE);
+ free_color_pair(&lastc);
+ if(promptc)
+ free_color_pair(&promptc);
+ }
+ else
+ EndInverse();
+
+ MoveCursor(real_y_base, x_base); /* Move the cursor to show we're done */
+ fflush(stdout);
+ resume_busy_cue(0);
+ if(km_popped){
+ FOOTER_ROWS(ps_global) = 1;
+ clearfooter(ps_global);
+ ps_global->mangled_body = 1;
+ }
+
+ return(return_v);
+}
+
+
+/*----------------------------------------------------------------------
+ Check to see if the given command is reasonably valid
+
+ Args: ch -- the character to check
+
+ Result: A valid command is returned, or a well know bad command is returned.
+
+ ---*/
+UCS
+validatekeys(UCS ch)
+{
+ if(F_ON(F_USE_FK,ps_global)){
+ if(ch >= 'a' && ch <= 'z')
+ return(KEY_JUNK);
+ }
+ else{
+ if(ch >= PF1 && ch <= PF12)
+ return(KEY_JUNK);
+ }
+
+ return(ch);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Prepend config'd commands to keyboard input
+
+ Args: ch -- pointer to storage for returned command
+
+ Returns: TRUE if we're passing back a useful command, FALSE otherwise
+
+ ---*/
+int
+process_config_input(UCS *ch)
+{
+ static char firsttime = (char) 1;
+ int c;
+ unsigned long octets_so_far, remaining_octets, ret = 0;
+ unsigned char *inputp;
+ UCS ucs;
+ unsigned char inputbuf[20];
+
+ /* commands in config file */
+ if(ps_global->initial_cmds && *ps_global->initial_cmds) {
+ /*
+ * There are a few commands that may require keyboard input before
+ * we enter the main command loop. That input should be interactive,
+ * not from our list of initial keystrokes.
+ */
+ if(ps_global->dont_use_init_cmds)
+ return(ret);
+
+ c = *ps_global->initial_cmds++;
+
+ /*
+ * Use enough bytes to make up a character and convert it to UCS-4.
+ */
+ if(c < 0x80 || c > KEY_BASE){
+ *ch = (UCS) c;
+ ret = 1;
+ }
+ else{
+ memset(inputbuf, 0, sizeof(inputbuf));
+ inputbuf[0] = (0xff & c);
+ octets_so_far = 1;
+
+ while(!ret){
+ remaining_octets = octets_so_far;
+ inputp = inputbuf;
+ ucs = (UCS) utf8_get(&inputp, &remaining_octets);
+ switch(ucs){
+ case U8G_ENDSTRG: /* incomplete character, wait */
+ case U8G_ENDSTRI: /* incomplete character, wait */
+ if(!*ps_global->initial_cmds || octets_so_far >= sizeof(inputbuf)){
+ *ch = BADESC;
+ ret = 1;
+ }
+ else
+ inputbuf[octets_so_far++] = (0xff & *ps_global->initial_cmds++);
+
+ break;
+
+ default:
+ if(ucs & U8G_ERROR || ucs == UBOGON)
+ *ch = BADESC;
+ else
+ *ch = ucs;
+
+ ret = 1;
+ break;
+ }
+ }
+ }
+
+ if(!*ps_global->initial_cmds && ps_global->free_initial_cmds){
+ fs_give((void **) &ps_global->free_initial_cmds);
+ ps_global->initial_cmds = NULL;
+ }
+
+ return(ret);
+ }
+
+ if(firsttime) {
+ firsttime = 0;
+ if(ps_global->in_init_seq) {
+ ps_global->in_init_seq = 0;
+ ps_global->save_in_init_seq = 0;
+ clear_cursor_pos();
+ F_SET(F_USE_FK,ps_global,ps_global->orig_use_fkeys);
+ /* draw screen */
+ *ch = (UCS) ctrl('L');
+ return(1);
+ }
+ }
+
+ return(0);
+}
+
+
+#define TAPELEN 256
+static int tape[TAPELEN];
+static long recorded = 0L;
+static short length = 0;
+
+
+/*
+ * record user keystrokes
+ *
+ * Args: ch -- the character to record
+ *
+ * Returns: character recorded
+ */
+int
+key_recorder(int ch)
+{
+ tape[recorded++ % TAPELEN] = ch;
+ if(length < TAPELEN)
+ length++;
+
+ return(ch);
+}
+
+
+/*
+ * playback user keystrokes
+ *
+ * Args: ch -- ignored
+ *
+ * Returns: character played back or -1 to indicate end of tape
+ */
+int
+key_playback(int ch)
+{
+ ch = length ? tape[(recorded + TAPELEN - length--) % TAPELEN] : -1;
+ return(ch);
+}
+
+
+/*
+ * recent_keystroke - verbose version of key_playback
+ */
+int
+recent_keystroke(int *cv, char *cs, size_t cslen)
+{
+ int c;
+
+ if((c = key_playback(0)) != -1){
+ *cv = c;
+ snprintf(cs, cslen, "%.32s", pretty_command(c));
+ return(0);
+ }
+
+ return(-1);
+}
+
+
+#ifdef _WINDOWS
+int
+pcpine_oe_cursor(col, row)
+ int col;
+ long row;
+{
+ return((row == g_mc_row
+ && col >= g_mc_col
+ && col < ps_global->ttyo->screen_cols)
+ ? MSWIN_CURSOR_IBEAM
+ : MSWIN_CURSOR_ARROW);
+}
+#endif
diff --git a/alpine/osdep/termin.gen.h b/alpine/osdep/termin.gen.h
new file mode 100644
index 00000000..18c7c0de
--- /dev/null
+++ b/alpine/osdep/termin.gen.h
@@ -0,0 +1,48 @@
+/*
+ * $Id: termin.gen.h 890 2007-12-21 05:34:43Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_TERMIN_GEN_INCLUDED
+#define PINE_OSDEP_TERMIN_GEN_INCLUDED
+
+#include <general.h>
+#include "../radio.h"
+
+/* Useful Macros */
+#define READ_COMMAND(U) (read_command_prep() ? read_command(U) : NO_OP_COMMAND)
+
+/* exported prototypes */
+UCS read_command(char **);
+int read_command_prep(void);
+int key_recorder(int);
+int optionally_enter(char *, int, int, int, char *, ESCKEY_S *, HelpType, int *);
+UCS validatekeys(UCS);
+int process_config_input(UCS *);
+int key_recorder(int);
+int key_playback(int);
+int recent_keystroke(int *, char *, size_t);
+int init_tty_driver(struct pine *);
+void end_tty_driver(struct pine *);
+int PineRaw(int);
+UCS read_char(int);
+void init_keyboard(int);
+void end_keyboard(int);
+int pre_screen_config_opt_enter(char *, int, char *,
+ ESCKEY_S *, HelpType, int *);
+#ifdef _WINDOWS
+int pcpine_oe_cursor(int, long);
+#endif
+
+#endif /* PINE_OSDEP_TERMIN_GEN_INCLUDED */
diff --git a/alpine/osdep/termin.unx.c b/alpine/osdep/termin.unx.c
new file mode 100644
index 00000000..451d18c2
--- /dev/null
+++ b/alpine/osdep/termin.unx.c
@@ -0,0 +1,752 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: termin.unx.c 1025 2008-04-08 22:59:38Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2008 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+#include <system.h>
+#include <general.h>
+
+#include "../../c-client/mail.h" /* for MAILSTREAM and friends */
+#include "../../c-client/osdep.h"
+#include "../../c-client/rfc822.h" /* for soutr_t and such */
+#include "../../c-client/misc.h" /* for cpystr proto */
+#include "../../c-client/utf8.h" /* for CHARSET and such*/
+#include "../../c-client/imap4r1.h"
+
+#include "../../pith/charconv/utf8.h"
+#include "../../pith/charconv/filesys.h"
+
+#include "../../pith/osdep/color.h"
+#include "../../pith/osdep/collate.h"
+#include "../../pith/osdep/err_desc.h"
+
+#include "../../pith/debug.h"
+#include "../../pith/state.h"
+#include "../../pith/conf.h"
+#include "../../pith/detach.h"
+#include "../../pith/adrbklib.h"
+#include "../../pith/remote.h"
+#include "../../pith/imap.h"
+#include "../../pith/status.h"
+
+#include "../pico/estruct.h"
+
+#include "../../pico/estruct.h"
+#include "../../pico/pico.h"
+#include "../../pico/osdep/raw.h"
+#include "../../pico/osdep/signals.h"
+#include "../../pico/osdep/mouse.h"
+#include "../../pico/osdep/read.h"
+#include "../../pico/osdep/getkey.h"
+#include "../../pico/osdep/tty.h"
+#include "../../pico/keydefs.h"
+
+#include "../talk.h"
+#include "../radio.h"
+#include "../dispfilt.h"
+#include "../signal.h"
+#include "../mailcmd.h"
+#include "../setup.h"
+
+#include "termin.gen.h"
+#include "termout.gen.h"
+#include "termin.unx.h"
+
+
+
+/*======================================================================
+ Things having to do with reading from the tty driver and keyboard
+ - initialize tty driver and reset tty driver
+ - read a character from terminal with keyboard escape seqence mapping
+ - initialize keyboard (keypad or such) and reset keyboard
+ - prompt user for a line of input
+ - read a command from keyboard with timeouts.
+
+ ====*/
+
+
+/*
+ * Helpful definitions
+ */
+/*
+ * Should really be using pico's TERM's t_getchar to read a character but
+ * we're just calling ttgetc directly for now. Ttgetc is the same as
+ * t_getchar whenever we use it so we're avoiding the trouble of initializing
+ * the TERM struct and calling ttgetc directly.
+ */
+#define READ_A_CHAR() ttgetc(NO_OP_COMMAND, key_rec, read_bail)
+
+
+/*
+ * Internal prototypes
+ */
+int pine_simple_ttgetc(int (*recorder)(int), void (*bail_handler)(void));
+UCS check_for_timeout(int);
+void read_bail(void);
+
+
+/*----------------------------------------------------------------------
+ Initialize the tty driver to do single char I/O and whatever else (UNIX)
+
+ Args: struct pine
+
+ Result: tty driver is put in raw mode so characters can be read one
+ at a time. Returns -1 if unsuccessful, 0 if successful.
+
+Some file descriptor voodoo to allow for pipes across vforks. See
+open_mailer for details.
+ ----------------------------------------------------------------------*/
+int
+init_tty_driver(struct pine *ps)
+{
+#ifdef MOUSE
+ if(F_ON(F_ENABLE_MOUSE, ps_global))
+ init_mouse();
+#endif /* MOUSE */
+
+ /* turn off talk permission by default */
+
+ if(F_ON(F_ALLOW_TALK, ps))
+ allow_talk(ps);
+ else
+ disallow_talk(ps);
+
+ return(PineRaw(1));
+}
+
+
+
+/*----------------------------------------------------------------------
+ Set or clear the specified tty mode
+
+ Args: ps -- struct pine
+ mode -- mode bits to modify
+ clear -- whether or not to clear or set
+
+ Result: tty driver mode change.
+ ----------------------------------------------------------------------*/
+void
+tty_chmod(struct pine *ps, int mode, int func)
+{
+ char *tty_name;
+ int new_mode;
+ struct stat sbuf;
+ static int saved_mode = -1;
+
+ /* if no problem figuring out tty's name & mode? */
+ if((((tty_name = (char *) ttyname(STDIN_FD)) != NULL
+ && fstat(STDIN_FD, &sbuf) == 0)
+ || ((tty_name = (char *) ttyname(STDOUT_FD)) != NULL
+ && fstat(STDOUT_FD, &sbuf) == 0))
+ && !(func == TMD_RESET && saved_mode < 0)){
+ new_mode = (func == TMD_RESET)
+ ? saved_mode
+ : (func == TMD_CLEAR)
+ ? (sbuf.st_mode & ~mode)
+ : (sbuf.st_mode | mode);
+ /* assign tty new mode */
+ if(our_chmod(tty_name, new_mode) == 0){
+ if(func == TMD_RESET) /* forget we knew */
+ saved_mode = -1;
+ else if(saved_mode < 0)
+ saved_mode = sbuf.st_mode; /* remember original */
+ }
+ }
+}
+
+
+
+/*----------------------------------------------------------------------
+ End use of the tty, put it back into it's normal mode (UNIX)
+
+ Args: ps -- struct pine
+
+ Result: tty driver mode change.
+ ----------------------------------------------------------------------*/
+void
+end_tty_driver(struct pine *ps)
+{
+ ps = ps; /* get rid of unused parameter warning */
+
+#ifdef MOUSE
+ end_mouse();
+#endif /* MOUSE */
+ fflush(stdout);
+ dprint((2, "about to end_tty_driver\n"));
+
+ tty_chmod(ps, 0, TMD_RESET);
+ PineRaw(0);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Actually set up the tty driver (UNIX)
+
+ Args: state -- which state to put it in. 1 means go into raw, 0 out of
+
+ Result: returns 0 if successful and < 0 if not.
+ ----*/
+int
+PineRaw(int state)
+{
+ int result;
+
+ result = Raw(state);
+
+ if(result == 0 && state == 1){
+ /*
+ * Only go into 8 bit mode if we are doing something other
+ * than plain ASCII. This will save the folks that have
+ * their parity on their serial lines wrong the trouble of
+ * getting it right
+ */
+ if((ps_global->keyboard_charmap && ps_global->keyboard_charmap[0] &&
+ strucmp(ps_global->keyboard_charmap, "us-ascii"))
+ || (ps_global->display_charmap && ps_global->display_charmap[0] &&
+ strucmp(ps_global->display_charmap, "us-ascii")))
+ bit_strip_off();
+
+#ifdef DEBUG
+ if(debug < 9) /* only on if full debugging set */
+#endif
+ quit_char_off();
+ ps_global->low_speed = ttisslow();
+ crlf_proc(0);
+ xonxoff_proc(F_ON(F_PRESERVE_START_STOP, ps_global));
+ }
+
+ return(result);
+}
+
+
+#if defined(SIGWINCH) && defined(TIOCGWINSZ)
+jmp_buf winch_state;
+int winch_occured = 0;
+int ready_for_winch = 0;
+#endif
+
+/*----------------------------------------------------------------------
+ This checks whether or not a character (UNIX)
+ is ready to be read, or it times out.
+
+ Args: time_out -- number of seconds before it will timeout
+
+ Result: Returns a NO_OP_IDLE or a NO_OP_COMMAND if the timeout expires
+ before input is available, or a KEY_RESIZE if a resize event
+ occurs, or READY_TO_READ if input is available before the timeout.
+ ----*/
+UCS
+check_for_timeout(int time_out)
+{
+ UCS res = NO_OP_COMMAND;
+
+ fflush(stdout);
+
+#if defined(SIGWINCH) && defined(TIOCGWINSZ)
+ if(!winch_occured){
+ if(setjmp(winch_state) != 0){
+ winch_occured = 1;
+ ready_for_winch = 0;
+
+ /*
+ * Need to unblock signal after longjmp from handler, because
+ * signal is normally unblocked upon routine exit from the handler.
+ */
+ our_sigunblock(SIGWINCH);
+ }
+ else
+ ready_for_winch = 1;
+ }
+
+ if(winch_occured){
+ winch_occured = ready_for_winch = 0;
+ fix_windsize(ps_global);
+ return(KEY_RESIZE);
+ }
+#endif /* SIGWINCH */
+
+ switch(res = input_ready(time_out)){
+ case BAIL_OUT:
+ read_bail(); /* non-tragic exit */
+ /* NO RETURN */
+
+ case PANIC_NOW:
+ panic1("Select error: %s\n", error_description(errno));
+ /* NO RETURN */
+
+ case READ_INTR:
+ res = NO_OP_COMMAND;
+ /* fall through */
+
+ case NO_OP_IDLE:
+ case NO_OP_COMMAND:
+ case READY_TO_READ:
+#if defined(SIGWINCH) && defined(TIOCGWINSZ)
+ ready_for_winch = 0;
+#endif
+ return(res);
+ }
+
+ /* not reachable */
+ return(res);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Read input characters with lots of processing for arrow keys and such (UNIX)
+
+ Args: time_out -- The timeout to for the reads
+
+ Result: returns the character read. Possible special chars.
+
+ This deals with function and arrow keys as well.
+
+ The idea is that this routine handles all escape codes so it done in
+ only one place. Especially so the back arrow key can work when entering
+ things on a line. Also so all function keys can be disabled and not
+ cause weird things to happen.
+ ---*/
+UCS
+read_char(int time_out)
+{
+ UCS status, cc, ch;
+ int (*key_rec)(int);
+
+ key_rec = key_recorder;
+ if(ps_global->conceal_sensitive_debugging)
+ key_rec = NULL;
+
+ /* Get input from initial-keystrokes */
+ if(process_config_input(&cc)){
+ ch = cc;
+ return(ch);
+ }
+
+ if((ch = check_for_timeout(time_out)) != READY_TO_READ)
+ goto done;
+
+ switch(status = kbseq(pine_simple_ttgetc, key_rec, read_bail,
+ ps_global->input_cs, &ch)){
+ case KEY_DOUBLE_ESC:
+ /*
+ * Special hack to get around comm devices eating control characters.
+ */
+ if(check_for_timeout(5) != READY_TO_READ){
+ dprint((9, "Read char: incomplete double escape timed out...\n"));
+ ch = KEY_JUNK; /* user typed ESC ESC, then stopped */
+ goto done;
+ }
+ else
+ ch = READ_A_CHAR();
+
+ ch &= 0x7f;
+
+ /* We allow a 3-digit number between 001 and 255 */
+ if(isdigit((unsigned char) ch)){
+ int n = 0, i = ch - '0';
+
+ if(i < 0 || i > 2){
+ dprint((9, "Read char: double escape followed by 1st digit not 0, 1, or 2... (%d)\n", i));
+ ch = KEY_JUNK;
+ goto done; /* bogus literal char value */
+ }
+
+ while(n++ < 2){
+ if(check_for_timeout(5) != READY_TO_READ
+ || (!isdigit((unsigned char) (ch = READ_A_CHAR()))
+ || (n == 1 && i == 2 && ch > '5')
+ || (n == 2 && i == 25 && ch > '5'))){
+ dprint((9, "Read char: bad double escape, either timed out or too large 3-digit num...\n"));
+ ch = KEY_JUNK; /* user typed ESC ESC #, stopped */
+ goto done;
+ }
+
+ i = (i * 10) + (ch - '0');
+ }
+
+ ch = i;
+ }
+ else{ /* or, normal case, ESC ESC c means ^c */
+ if(islower((unsigned char) ch)) /* canonicalize if alpha */
+ ch = toupper((unsigned char) ch);
+
+ ch = (isalpha((unsigned char)ch) || ch == '@'
+ || (ch >= '[' && ch <= '_'))
+ ? ctrl(ch) : ((ch == SPACE) ? ctrl('@'): ch);
+ dprint((9, "Read char: this is a successful double escape...\n"));
+ }
+
+ goto done;
+
+#ifdef MOUSE
+ case KEY_XTERM_MOUSE:
+ if(mouseexist()){
+ /*
+ * Special hack to get mouse events from an xterm.
+ * Get the details, then pass it past the keymenu event
+ * handler, and then to the installed handler if there
+ * is one...
+ */
+ static int down = 0;
+ int x, y, button;
+ unsigned long cmd;
+
+ clear_cursor_pos();
+ button = READ_A_CHAR() & 0x03;
+
+ x = READ_A_CHAR() - '!';
+ y = READ_A_CHAR() - '!';
+
+ ch = NO_OP_COMMAND;
+ if(button == 0){ /* xterm button 1 down */
+ down = 1;
+ if(checkmouse(&cmd, 1, x, y))
+ ch = cmd;
+ }
+ else if (down && button == 3){
+ down = 0;
+ if(checkmouse(&cmd, 0, x, y))
+ ch = cmd;
+ }
+
+ goto done;
+ }
+
+ break;
+#endif /* MOUSE */
+
+ case KEY_UP :
+ case KEY_DOWN :
+ case KEY_RIGHT :
+ case KEY_LEFT :
+ case KEY_PGUP :
+ case KEY_PGDN :
+ case KEY_HOME :
+ case KEY_END :
+ case KEY_DEL :
+ case PF1 :
+ case PF2 :
+ case PF3 :
+ case PF4 :
+ case PF5 :
+ case PF6 :
+ case PF7 :
+ case PF8 :
+ case PF9 :
+ case PF10 :
+ case PF11 :
+ case PF12 :
+ dprint((9, "Read char returning: 0x%x %s\n", status, pretty_command(status)));
+ return(status);
+
+ case CTRL_KEY_UP :
+ status = KEY_UP;
+ dprint((9, "Read char returning: 0x%x %s (for CTRL_KEY_UP)\n", status, pretty_command(status)));
+ return(status);
+
+ case CTRL_KEY_DOWN :
+ status = KEY_DOWN;
+ dprint((9, "Read char returning: 0x%x %s (for CTRL_KEY_DOWN)\n", status, pretty_command(status)));
+ return(status);
+
+ case CTRL_KEY_RIGHT :
+ status = KEY_RIGHT;
+ dprint((9, "Read char returning: 0x%x %s (for CTRL_KEY_RIGHT)\n", status, pretty_command(status)));
+ return(status);
+
+ case CTRL_KEY_LEFT :
+ status = KEY_LEFT;
+ dprint((9, "Read char returning: 0x%x %s (for CTRL_KEY_LEFT)\n", status, pretty_command(status)));
+ return(status);
+
+ case KEY_SWALLOW_Z:
+ status = KEY_JUNK;
+ case KEY_SWAL_UP:
+ case KEY_SWAL_DOWN:
+ case KEY_SWAL_LEFT:
+ case KEY_SWAL_RIGHT:
+ do
+ if(check_for_timeout(2) != READY_TO_READ){
+ status = KEY_JUNK;
+ break;
+ }
+ while(!strchr("~qz", READ_A_CHAR()));
+ ch = (status == KEY_JUNK) ? status : status - (KEY_SWAL_UP - KEY_UP);
+ goto done;
+
+ case KEY_KERMIT:
+ do{
+ cc = ch;
+ if(check_for_timeout(2) != READY_TO_READ){
+ status = KEY_JUNK;
+ break;
+ }
+ else
+ ch = READ_A_CHAR();
+ }while(cc != '\033' && ch != '\\');
+
+ ch = KEY_JUNK;
+ goto done;
+
+ case BADESC:
+ ch = KEY_JUNK;
+ goto done;
+
+ case 0: /* regular character */
+ default:
+ /*
+ * we used to strip (ch &= 0x7f;), but this seems much cleaner
+ * in the face of line noise and has the benefit of making it
+ * tougher to emit mistakenly labeled MIME...
+ */
+ if((ch & ~0x7f)
+ && ((!ps_global->keyboard_charmap || !strucmp(ps_global->keyboard_charmap, "US-ASCII"))
+ && (!ps_global->display_charmap || !strucmp(ps_global->display_charmap, "US-ASCII")))){
+ dprint((9, "Read char sees ch = 0x%x status=0x%x, returns KEY_JUNK\n", ch, status));
+ return(KEY_JUNK);
+ }
+ else if(ch == ctrl('Z')){
+ dprint((9, "Read char got ^Z, calling do_suspend\n"));
+ ch = do_suspend();
+ dprint((9, "After do_suspend Read char returns 0x%x %s\n", ch, pretty_command(ch)));
+ return(ch);
+ }
+#ifdef MOUSE
+ else if(ch == ctrl('\\')){
+ int e;
+
+ dprint((9, "Read char got ^\\, toggle xterm mouse\n"));
+ if(F_ON(F_ENABLE_MOUSE, ps_global)){
+ (e=mouseexist()) ? end_mouse() : (void) init_mouse();
+ if(e != mouseexist())
+ q_status_message1(SM_ASYNC, 0, 2, "Xterm mouse tracking %s!",
+ mouseexist() ? "on" : "off");
+ else if(!e)
+ q_status_message1(SM_ASYNC, 0, 2, "See help for feature \"%s\" ($DISPLAY variable set?)", pretty_feature_name(feature_list_name(F_ENABLE_MOUSE), -1));
+ }
+ else
+ q_status_message1(SM_ASYNC, 0, 2, "Feature \"%s\" not enabled",
+ pretty_feature_name(feature_list_name(F_ENABLE_MOUSE), -1));
+
+ return(NO_OP_COMMAND);
+ }
+#endif /* MOUSE */
+
+
+ done:
+#ifdef DEBUG
+ if(ps_global->conceal_sensitive_debugging && debug < 10){
+ dprint((9, "Read char returning: <hidden char>\n"));
+ }
+ else{
+ dprint((9, "Read char returning: 0x%x %s\n", ch, pretty_command(ch)));
+ }
+#endif
+
+ return(ch);
+ }
+
+ /* not reachable */
+ return(KEY_JUNK);
+}
+
+
+/*----------------------------------------------------------------------
+ Reading input somehow failed and we need to shutdown now
+
+ Args: none
+
+ Result: pine exits
+
+ ---*/
+void
+read_bail(void)
+{
+ dprint((1, "read_bail: cleaning up\n"));
+ end_signals(1);
+
+ /*
+ * This gets rid of temporary cache files for remote addrbooks.
+ */
+ completely_done_with_adrbks();
+
+ /*
+ * This flushes out deferred changes and gets rid of temporary cache
+ * files for remote config files.
+ */
+ if(ps_global->prc){
+ if(ps_global->prc->outstanding_pinerc_changes)
+ write_pinerc(ps_global, Main, WRP_NOUSER);
+
+ if(ps_global->prc->rd)
+ rd_close_remdata(&ps_global->prc->rd);
+
+ free_pinerc_s(&ps_global->prc);
+ }
+
+ /* as does this */
+ if(ps_global->post_prc){
+ if(ps_global->post_prc->outstanding_pinerc_changes)
+ write_pinerc(ps_global, Post, WRP_NOUSER);
+
+ if(ps_global->post_prc->rd)
+ rd_close_remdata(&ps_global->post_prc->rd);
+
+ free_pinerc_s(&ps_global->post_prc);
+ }
+
+ sp_end();
+
+ dprint((1, "done with read_bail clean up\n"));
+
+ imap_flush_passwd_cache(TRUE);
+ end_keyboard(F_ON(F_USE_FK,ps_global));
+ end_tty_driver(ps_global);
+ if(filter_data_file(0))
+ our_unlink(filter_data_file(0));
+
+ exit(0);
+}
+
+
+int
+pine_simple_ttgetc(int (*fi)(int), void (*fv)(void))
+{
+ int ch;
+
+#if defined(SIGWINCH) && defined(TIOCGWINSZ)
+ if(!winch_occured){
+ if(setjmp(winch_state) != 0){
+ winch_occured = 1;
+ ready_for_winch = 0;
+
+ /*
+ * Need to unblock signal after longjmp from handler, because
+ * signal is normally unblocked upon routine exit from the handler.
+ */
+ our_sigunblock(SIGWINCH);
+ }
+ else
+ ready_for_winch = 1;
+ }
+
+ if(winch_occured){
+ winch_occured = ready_for_winch = 0;
+ fix_windsize(ps_global);
+ return(KEY_RESIZE);
+ }
+#endif /* SIGWINCH */
+
+ ch = simple_ttgetc(fi, fv);
+
+#if defined(SIGWINCH) && defined(TIOCGWINSZ)
+ ready_for_winch = 0;
+#endif
+
+ return(ch);
+}
+
+
+
+extern char term_name[];
+/* -------------------------------------------------------------------
+ Set up the keyboard -- usually enable some function keys (UNIX)
+
+ Args: struct pine
+
+So far all we do here is turn on keypad mode for certain terminals
+
+Hack for NCSA telnet on an IBM PC to put the keypad in the right mode.
+This is the same for a vtXXX terminal or [zh][12]9's which we have
+a lot of at UW
+ ----*/
+void
+init_keyboard(int use_fkeys)
+{
+ if(use_fkeys && (!strucmp(term_name,"vt102")
+ || !strucmp(term_name,"vt100")))
+ printf("\033\133\071\071\150");
+}
+
+
+
+/*----------------------------------------------------------------------
+ Clear keyboard, usually disable some function keys (UNIX)
+
+ Args: pine state (terminal type)
+
+ Result: keyboard state reset
+ ----*/
+void
+end_keyboard(int use_fkeys)
+{
+ if(use_fkeys && (!strcmp(term_name, "vt102")
+ || !strcmp(term_name, "vt100"))){
+ printf("\033\133\071\071\154");
+ fflush(stdout);
+ }
+}
+
+
+/*
+ * This is a bare-bones implementation which is missing most of the
+ * features of the real optionally_enter. The initial value of string is
+ * isgnored. The escape_list is ignored. The help is not implemented. The
+ * only flag implemented is OE_PASSWD. We don't go into raw mode so the
+ * only input possible is a line (the EOL is stripped before returning).
+ */
+int
+pre_screen_config_opt_enter(char *string, int string_size, char *prompt,
+ ESCKEY_S *escape_list, HelpType help, int *flags)
+{
+ char *pw;
+ int return_v = -10;
+
+ while(return_v == -10) {
+
+ if(flags && (*flags & (OE_PASSWD | OE_PASSWD_NOAST))){
+ if((pw = getpass(prompt)) != NULL){
+ if(strlen(pw) < string_size){
+ strncpy(string, pw, string_size);
+ string[string_size-1] = '\0';
+ return_v = 0;
+ }
+ else{
+ fputs("Password too long\n", stderr);
+ return_v = -1;
+ }
+ }
+ else
+ return_v = 1; /* cancel? */
+ }
+ else{
+ char *p;
+
+ fputs(prompt, stdout);
+ fgets(string, string_size, stdin);
+ string[string_size-1] = '\0';
+ if((p = strpbrk(string, "\r\n")) != NULL)
+ *p = '\0';
+
+ return_v = 0;
+ }
+ }
+
+ return(return_v);
+}
+
+
diff --git a/alpine/osdep/termin.unx.h b/alpine/osdep/termin.unx.h
new file mode 100644
index 00000000..7ead09f0
--- /dev/null
+++ b/alpine/osdep/termin.unx.h
@@ -0,0 +1,29 @@
+/*
+ * $Id: termin.unx.h 769 2007-10-24 00:15:40Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_TERMIN_UNX_INCLUDED
+#define PINE_OSDEP_TERMIN_UNX_INCLUDED
+
+
+#include <general.h>
+
+
+/* exported prototypes */
+void tty_chmod(struct pine *, int, int);
+
+
+
+#endif /* PINE_OSDEP_TERMIN_UNX_INCLUDED */
diff --git a/alpine/osdep/termin.wnt.c b/alpine/osdep/termin.wnt.c
new file mode 100644
index 00000000..83dc8284
--- /dev/null
+++ b/alpine/osdep/termin.wnt.c
@@ -0,0 +1,352 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: termin.unx.c 193 2006-10-20 17:09:26Z mikes@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2008 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#include <system.h>
+#include <general.h>
+
+#include "../../c-client/mail.h" /* for MAILSTREAM and friends */
+#include "../../c-client/osdep.h"
+#include "../../c-client/rfc822.h" /* for soutr_t and such */
+#include "../../c-client/misc.h" /* for cpystr proto */
+#include "../../c-client/utf8.h" /* for CHARSET and such*/
+#include "../../c-client/imap4r1.h"
+
+#include "../../pith/charconv/utf8.h"
+#include "../../pith/charconv/filesys.h"
+
+#include "../../pith/osdep/color.h"
+
+#include "../../pith/debug.h"
+#include "../../pith/state.h"
+#include "../../pith/conf.h"
+#include "../../pith/detach.h"
+
+#include "../pico/estruct.h"
+#include "../pico/pico.h"
+
+#include "../../pico/osdep/raw.h"
+#include "../../pico/osdep/signals.h"
+#include "../../pico/osdep/mouse.h"
+#include "../../pico/keydefs.h"
+
+#include "../talk.h"
+#include "../radio.h"
+#include "../dispfilt.h"
+#include "../signal.h"
+#include "../status.h"
+#include "../titlebar.h"
+
+#include "../../pico/osdep/mswin.h"
+
+#include "termin.gen.h"
+#include "termin.wnt.h"
+#include "termout.gen.h"
+
+#define RETURN_CH(X) return(key_rec ? ((*key_rec)(X)) : (int)(X))
+
+/* global to tell us if the window was resized. */
+static int DidResize = FALSE;
+
+int pine_window_resize_callback(void);
+
+/*----------------------------------------------------------------------
+ Initialize the tty driver to do single char I/O and whatever else
+
+ Input: struct pine
+
+ Result: tty driver is put in raw mode
+ ----------------------------------------------------------------------*/
+int
+init_tty_driver(struct pine *pine)
+{
+ mswin_showwindow();
+ mswin_setresizecallback (pine_window_resize_callback);
+ init_mouse (); /* always a mouse under windows? */
+ return(PineRaw(1));
+}
+
+
+/*----------------------------------------------------------------------
+ End use of the tty, put it back into it's normal mode
+
+ Input: struct pine
+
+ Result: tty driver mode change
+ ----------------------------------------------------------------------*/
+void
+end_tty_driver(struct pine *pine)
+{
+ dprint((2, "about to end_tty_driver\n"));
+ mswin_clearresizecallback (pine_window_resize_callback);
+}
+
+/*----------------------------------------------------------------------
+ Actually set up the tty driver
+
+ Args: state -- which state to put it in. 1 means go into raw, 0 out of
+
+ Result: returns 0 if successful and -1 if not.
+ ----*/
+
+int
+PineRaw(int state)
+{
+ ps_global->low_speed = 0;
+ return(0);
+}
+
+/*----------------------------------------------------------------------
+ Read input characters with lots of processing for arrow keys and such
+
+ Input: none
+
+ Result: returns the character read. Possible special chars defined h file
+
+
+ This deals with function and arrow keys as well.
+ It returns ^T for up , ^U for down, ^V for forward and ^W for back.
+ These are just sort of arbitrarily picked and might be changed.
+ They are defined in defs.h. Didn't want to use 8 bit chars because
+ the values are signed chars, though it ought to work with negative
+ values.
+
+ The idea is that this routine handles all escape codes so it done in
+ only one place. Especially so the back arrow key can work when entering
+ things on a line. Also so all function keys can be broken and not
+ cause weird things to happen.
+----------------------------------------------------------------------*/
+
+UCS
+read_char(int tm)
+{
+ unsigned ch = 0;
+ time_t timein;
+ int (*key_rec)(int);
+
+ key_rec = key_recorder;
+ if(ps_global->conceal_sensitive_debugging && debug < 10)
+ key_rec = NULL;
+
+ if(process_config_input((int *) &ch))
+ RETURN_CH(ch);
+
+ if (DidResize) {
+ DidResize = FALSE;
+ fix_windsize(ps_global);
+ return(KEY_RESIZE);
+ }
+
+ mswin_setcursor(MSWIN_CURSOR_ARROW);
+
+ if(tm){
+ timein = time(0L);
+ /* mswin_charavail() Yields control to other window apps. */
+ while (!mswin_charavail()) {
+ if(time(0L) >= timein + (time_t) tm){
+ ch = (tm < IDLE_TIMEOUT) ? NO_OP_COMMAND : NO_OP_IDLE;
+ goto gotone;
+ }
+ if (DidResize) {
+ DidResize = FALSE;
+ fix_windsize(ps_global);
+ return(KEY_RESIZE);
+ }
+ if(checkmouse(&ch,0,0,0))
+ goto gotone;
+ }
+ }
+ else
+ while(!mswin_charavail())
+ if(checkmouse(&ch,0,0,0))
+ goto gotone;
+
+ ch = mswin_getc_fast();
+
+ /*
+ * mswin_getc_fast() returns UCS type codes (see keydefs.h). Map
+ * those values to what is expected from read_char(): Ctrl keys being
+ * in the 0..0x1f range, NO_OP_COMMAND, etc.
+ */
+ if(ch == NODATA)
+ ch = NO_OP_COMMAND;
+ else if(ch & CTRL)
+ {
+ ch &= ~CTRL;
+ if(ch >= '@' && ch < '@' + 32) {
+ ch -= '@';
+ }
+ else {
+ /*
+ * This could be a ctrl key this part of Pine doesn't understand.
+ * For example, CTRL|KEY_LEFT. Map these to nops.
+ */
+ ch = NO_OP_COMMAND;
+ }
+ }
+
+gotone:
+ /* More obtuse key mapping. If it is a mouse event, the return
+ * may be KEY_MOUSE, which indicates to the upper layer that it
+ * is a mouse event. Return it here to avoid the code that
+ * follows which would do a (ch & 0xff).
+ */
+ if (ch == KEY_MOUSE)
+ RETURN_CH(ch);
+
+ /*
+ * WARNING: Hack notice.
+ * the mouse interaction complicates this expression a bit as
+ * if function key mode is set, PFn values are setup for return
+ * by the mouse event catcher. For now, just special case them
+ * since they don't conflict with any of the DOS special keys.
+ */
+ if((ch & 0xff) == ctrl('Z'))
+ RETURN_CH(do_suspend());
+
+ RETURN_CH (ch);
+}
+
+void
+flush_input(void)
+{
+ mswin_flush_input();
+}
+
+void
+init_keyboard(int use_fkeys)
+{
+}
+
+void
+end_keyboard(int use_fkeys)
+{
+}
+
+int
+pre_screen_config_opt_enter(char *utf8string, int utf8string_size,
+ char *utf8prompt, ESCKEY_S *escape_list,
+ HelpType help, int *flags)
+{
+ mswin_setwindow(NULL, NULL, NULL, NULL, NULL, NULL);
+ return(win_dialog_opt_enter(utf8string, utf8string_size, utf8prompt, escape_list,
+ help, flags));
+}
+
+int
+win_dialog_opt_enter(char *utf8string, int utf8string_size, char *utf8prompt,
+ ESCKEY_S *escape_list, HelpType help, int *flags)
+{
+ MDlgButton button_list[12];
+ LPTSTR free_names[12];
+ LPTSTR free_labels[12];
+ int i, b, return_v;
+ char **help_text;
+ char *utf8, *saved_string = NULL;
+ UCS *string, *s, *prompt;
+ int n;
+
+ memset(&free_names, 0, sizeof(LPTSTR) * 12);
+ memset(&free_labels, 0, sizeof(LPTSTR) * 12);
+ memset (&button_list, 0, sizeof (MDlgButton) * 12);
+ b = 0;
+ for (i = 0; escape_list && escape_list[i].ch != -1 && i < 11; ++i) {
+ if (escape_list[i].name != NULL
+ && escape_list[i].ch > 0 && escape_list[i].ch < 256) {
+ button_list[b].ch = escape_list[i].ch;
+ button_list[b].rval = escape_list[i].rval;
+ free_names[b] = utf8_to_lptstr(escape_list[i].name);
+ button_list[b].name = free_names[b];
+ free_labels[b] = utf8_to_lptstr(escape_list[i].label);
+ button_list[b].label = free_labels[b];
+ b++;
+ }
+ }
+
+ button_list[b].ch = -1;
+
+ if(utf8string)
+ saved_string = cpystr(utf8string);
+
+ /* assumption here is that HelpType is char ** */
+ help_text = help;
+
+ n = utf8string_size;
+ string = (UCS *) fs_get(n * sizeof(UCS));
+ s = utf8_to_ucs4_cpystr(utf8string);
+ if(s){
+ ucs4_strncpy(string, s, n);
+ string[n-1] = '\0';
+ fs_give((void **) &s);
+ }
+
+ prompt = utf8_to_ucs4_cpystr(utf8prompt ? utf8prompt : "");
+
+ return_v = mswin_dialog(prompt, string, n,
+ (flags && *flags & OE_APPEND_CURRENT),
+ (flags && *flags & OE_PASSWD_NOAST) ? 10 :
+ (flags && *flags & OE_PASSWD) ? 1 : 0,
+ button_list,
+ help_text, flags ? *flags : OE_NONE);
+
+ for(i = 0; i < 12; i++){
+ if(free_names[i])
+ fs_give((void **) &free_names[i]);
+ if(free_labels[i])
+ fs_give((void **) &free_labels[i]);
+ }
+
+ utf8 = ucs4_to_utf8_cpystr(string);
+ if(utf8){
+ strncpy(utf8string, utf8, utf8string_size);
+ utf8string[utf8string_size-1] = '\0';
+ fs_give((void **) &utf8);
+ }
+
+ if(string)
+ fs_give((void **) &string);
+
+ if(prompt)
+ fs_give((void **) &prompt);
+
+ if(flags && (saved_string && !utf8string || !saved_string && utf8string ||
+ (saved_string && string && strcmp(saved_string, utf8string))))
+ *flags |= OE_USER_MODIFIED;
+
+ if(saved_string)
+ fs_give((void **) &saved_string);
+
+ return(return_v);
+}
+
+
+/*----------------------------------------------------------------------
+ Flag the fact the window has resized.
+*/
+int
+pine_window_resize_callback (void)
+{
+ DidResize = TRUE;
+ return(0);
+}
+
+void
+intr_proc(int state)
+{
+ return; /* no op */
+}
+
diff --git a/alpine/osdep/termin.wnt.h b/alpine/osdep/termin.wnt.h
new file mode 100644
index 00000000..68480852
--- /dev/null
+++ b/alpine/osdep/termin.wnt.h
@@ -0,0 +1,32 @@
+/*
+ * $Id: termin.unx.h 136 2006-09-22 20:06:05Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_TERMIN_WNT_INCLUDED
+#define PINE_OSDEP_TERMIN_WNT_INCLUDED
+
+
+#include <general.h>
+#include "../radio.h"
+#include "../../pith/helptext.h"
+
+
+/* exported prototypes */
+void flush_input(void);
+int win_dialog_opt_enter(char *, int, char *, ESCKEY_S *, HelpType, int *);
+void intr_proc(int);
+
+
+#endif /* PINE_OSDEP_TERMIN_WNT_INCLUDED */
diff --git a/alpine/osdep/termout.gen.c b/alpine/osdep/termout.gen.c
new file mode 100644
index 00000000..a006c694
--- /dev/null
+++ b/alpine/osdep/termout.gen.c
@@ -0,0 +1,584 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: termout.gen.c 1012 2008-03-26 00:44:22Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2008 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+#include <system.h>
+#include <general.h>
+
+#include "../../c-client/mail.h" /* for MAILSTREAM and friends */
+#include "../../c-client/osdep.h"
+#include "../../c-client/rfc822.h" /* for soutr_t and such */
+#include "../../c-client/misc.h" /* for cpystr proto */
+#include "../../c-client/utf8.h" /* for CHARSET and such*/
+#include "../../c-client/imap4r1.h"
+
+#include "../../pith/osdep/color.h"
+#include "../../pith/charconv/filesys.h"
+
+#include "../../pith/debug.h"
+#include "../../pith/newmail.h"
+#include "../../pith/filter.h"
+#include "../../pith/handle.h"
+#include "../../pith/conf.h"
+#include "../../pith/mimedesc.h"
+
+#include "../../pico/estruct.h"
+#include "../../pico/pico.h"
+#include "../../pico/keydefs.h"
+#include "../../pico/osdep/color.h"
+
+#include "../status.h"
+#include "../radio.h"
+#include "../folder.h"
+#include "../keymenu.h"
+#include "../send.h"
+#include "../mailindx.h"
+
+int _line = FARAWAY;
+int _col = FARAWAY;
+
+#include "termout.gen.h"
+
+
+#define PUTLINE_BUFLEN 256
+
+
+
+/*
+ * Generic tty output routines...
+ */
+
+/*----------------------------------------------------------------------
+ Printf style output line to the screen at given position, 0 args
+
+ Args: x -- column position on the screen
+ y -- row position on the screen
+ line -- line of text to output
+
+ Result: text is output
+ cursor position is update
+ ----*/
+void
+PutLine0(int x, int y, register char *line)
+{
+ MoveCursor(x,y);
+ Write_to_screen(line);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Output line of length len to the display observing embedded attributes
+
+ Args: x -- column position on the screen
+ y -- column position on the screen
+ line -- text to be output
+ length -- length of text to be output
+
+ Result: text is output
+ cursor position is updated
+ ----------------------------------------------------------------------*/
+void
+PutLine0n8b(int x, int y, register char *line, int length, HANDLE_S *handles)
+{
+ unsigned char c;
+ int is_inv = 0, is_bold = 0, is_uline = 0, is_fg = 0, is_bg = 0;
+#ifdef _WINDOWS
+ int hkey = 0;
+#endif
+
+ MoveCursor(x,y);
+
+ while(length--){
+
+ c = (unsigned char) *line++;
+
+ if(c == (unsigned char) TAG_EMBED && length){
+
+ length--;
+
+ switch(*line++){
+ case TAG_INVON :
+ StartInverse();
+ is_inv = 1;
+ break;
+
+ case TAG_INVOFF :
+ EndInverse();
+ is_inv = 0;
+ break;
+
+ case TAG_BOLDON :
+ StartBold();
+ is_bold = 1;
+ break;
+
+ case TAG_BOLDOFF :
+ EndBold();
+ is_bold = 0;
+ break;
+
+ case TAG_ITALICON : /* express italic as uline in terminal */
+ case TAG_ULINEON :
+ StartUnderline();
+ is_uline = 1;
+ break;
+
+ case TAG_ITALICOFF : /* express italic as uline in terminal */
+ case TAG_ULINEOFF :
+ EndUnderline();
+ is_uline = 0;
+ break;
+
+ case TAG_HANDLE :
+ length -= *line + 1; /* key length plus length tag */
+ if(handles){
+ int key, n, current_key = 0;
+
+ for(key = 0, n = *line++; n; n--) /* forget Horner? */
+ key = (key * 10) + (*line++ - '0');
+
+#if _WINDOWS
+ hkey = key;
+#endif
+
+ if(handles->using_is_used){
+ HANDLE_S *h;
+
+ for(h = handles; h; h = h->next)
+ if(h->is_used)
+ break;
+
+ if(h)
+ current_key = h->key;
+ }
+ else
+ current_key = handles->key;
+
+ if(key == current_key){
+ COLOR_PAIR *curcolor = NULL;
+ COLOR_PAIR *revcolor = NULL;
+
+ if(handles->color_unseen
+ && (curcolor = pico_get_cur_color())
+ && (colorcmp(curcolor->fg, ps_global->VAR_NORM_FORE_COLOR)
+ || colorcmp(curcolor->bg, ps_global->VAR_NORM_BACK_COLOR))
+ && (revcolor = apply_rev_color(curcolor,
+ ps_global->index_color_style)))
+ (void) pico_set_colorp(revcolor, PSC_NONE);
+ else{
+
+ if(pico_usingcolor() &&
+ ps_global->VAR_SLCTBL_FORE_COLOR &&
+ ps_global->VAR_SLCTBL_BACK_COLOR){
+ pico_set_normal_color();
+ }
+ else
+ EndBold();
+
+ StartInverse();
+ is_inv = 1;
+ }
+
+ if(curcolor)
+ free_color_pair(&curcolor);
+
+ if(revcolor)
+ free_color_pair(&revcolor);
+ }
+ }
+ else{
+ /* BUG: complain? */
+ line += *line + 1;
+ }
+
+ break;
+
+ case TAG_FGCOLOR :
+ if(length < RGBLEN){
+ dprint((9,
+ "FGCOLOR not proper length, ignoring\n"));
+ length = 0;
+ break;
+ }
+
+ (void)pico_set_fg_color(line);
+ is_fg = 1;
+ length -= RGBLEN;
+ line += RGBLEN;
+ break;
+
+ case TAG_BGCOLOR :
+ if(length < RGBLEN){
+ dprint((9,
+ "BGCOLOR not proper length, ignoring\n"));
+ length = 0;
+ break;
+ }
+
+ (void)pico_set_bg_color(line);
+ is_bg = 1;
+ length -= RGBLEN;
+ line += RGBLEN;
+ break;
+
+ case TAG_EMBED: /* literal "embed" char */
+ Writechar(TAG_EMBED, 0);
+ break;
+
+ case TAG_STRIKEON : /* unsupported text markup */
+ case TAG_STRIKEOFF :
+ case TAG_BIGON :
+ case TAG_BIGOFF :
+ case TAG_SMALLON :
+ case TAG_SMALLOFF :
+ default : /* Eat unrecognized tag - TAG_BIGON, etc */
+ break;
+ } /* tag with handle, skip it */
+ }
+ else
+ Writechar(c, 0);
+ }
+
+
+#if _WINDOWS_X
+ if(hkey) {
+ char *tmp_file = NULL, ext[32], mtype[128];
+ HANDLE_S *h;
+ extern HANDLE_S *get_handle (HANDLE_S *, int);
+
+ if((h = get_handle(handles, hkey)) && h->type == Attach){
+ ext[0] = '\0';
+ strncpy(mtype, body_type_names(h->h.attach->body->type), sizeof(mtype));
+ mtype[sizeof(mtype)-1] = '\0';
+ if (h->h.attach->body->subtype) {
+ strncat (mtype, "/", sizeof(mtype)-strlen(mtype)-1);
+ mtype[sizeof(mtype)-1] = '\0';
+ strncat (mtype, h->h.attach->body->subtype, sizeof(mtype)-strlen(mtype)-1);
+ mtype[sizeof(mtype)-1] = '\0';
+ }
+
+ if(!set_mime_extension_by_type(ext, mtype)){
+ char *p, *extp = NULL;
+
+ if((p = get_filename_parameter(NULL, 0, h->h.attach->body, &extp)) != NULL){
+ if(extp){
+ strncpy(ext, extp, sizeof(ext));
+ ext[sizeof(ext)-1] = '\0';
+ }
+
+ fs_give((void **) &p);
+ }
+ }
+
+ if(ext[0] && (tmp_file = temp_nam_ext(NULL, "im", ext))){
+ FILE *f = our_fopen(tmp_file, "w");
+
+ mswin_registericon(x, h->key, tmp_file);
+
+ fclose(f);
+ our_unlink(tmp_file);
+ fs_give((void **)&tmp_file);
+ }
+ }
+ }
+#endif
+ if(is_inv){
+ dprint((9,
+ "INVERSE left on at end of line, turning off now\n"));
+ EndInverse();
+ }
+ if(is_bold){
+ dprint((9,
+ "BOLD left on at end of line, turning off now\n"));
+ EndBold();
+ }
+ if(is_uline){
+ dprint((9,
+ "UNDERLINE left on at end of line, turning off now\n"));
+ EndUnderline();
+ }
+ if(is_fg || is_bg)
+ pico_set_normal_color();
+
+}
+
+
+/*----------------------------------------------------------------------
+ Printf style output line to the screen at given position, 1 arg
+
+ Input: position on the screen
+ line of text to output
+
+ Result: text is output
+ cursor position is update
+ ----------------------------------------------------------------------*/
+void
+/*VARARGS2*/
+PutLine1(int x, int y, char *line, void *arg1)
+{
+ char buffer[PUTLINE_BUFLEN];
+
+ snprintf(buffer, sizeof(buffer), line, arg1);
+ buffer[sizeof(buffer)-1] = '\0';
+ PutLine0(x, y, buffer);
+}
+
+
+/*----------------------------------------------------------------------
+ Printf style output line to the screen at given position, 2 args
+
+ Input: position on the screen
+ line of text to output
+
+ Result: text is output
+ cursor position is update
+ ----------------------------------------------------------------------*/
+void
+/*VARARGS3*/
+PutLine2(int x, int y, char *line, void *arg1, void *arg2)
+{
+ char buffer[PUTLINE_BUFLEN];
+
+ snprintf(buffer, sizeof(buffer), line, arg1, arg2);
+ buffer[sizeof(buffer)-1] = '\0';
+ PutLine0(x, y, buffer);
+}
+
+
+/*----------------------------------------------------------------------
+ Printf style output line to the screen at given position, 3 args
+
+ Input: position on the screen
+ line of text to output
+
+ Result: text is output
+ cursor position is update
+ ----------------------------------------------------------------------*/
+void
+/*VARARGS4*/
+PutLine3(int x, int y, char *line, void *arg1, void *arg2, void *arg3)
+{
+ char buffer[PUTLINE_BUFLEN];
+
+ snprintf(buffer, sizeof(buffer), line, arg1, arg2, arg3);
+ buffer[sizeof(buffer)-1] = '\0';
+ PutLine0(x, y, buffer);
+}
+
+
+/*----------------------------------------------------------------------
+ Printf style output line to the screen at given position, 4 args
+
+ Args: x -- column position on the screen
+ y -- column position on the screen
+ line -- printf style line of text to output
+
+ Result: text is output
+ cursor position is update
+ ----------------------------------------------------------------------*/
+void
+/*VARARGS5*/
+PutLine4(int x, int y, char *line, void *arg1, void *arg2, void *arg3, void *arg4)
+{
+ char buffer[PUTLINE_BUFLEN];
+
+ snprintf(buffer, sizeof(buffer), line, arg1, arg2, arg3, arg4);
+ buffer[sizeof(buffer)-1] = '\0';
+ PutLine0(x, y, buffer);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Printf style output line to the screen at given position, 5 args
+
+ Args: x -- column position on the screen
+ y -- column position on the screen
+ line -- printf style line of text to output
+
+ Result: text is output
+ cursor position is update
+ ----------------------------------------------------------------------*/
+void
+/*VARARGS6*/
+PutLine5(int x, int y, char *line, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5)
+{
+ char buffer[PUTLINE_BUFLEN];
+
+ snprintf(buffer, sizeof(buffer), line, arg1, arg2, arg3, arg4, arg5);
+ buffer[sizeof(buffer)-1] = '\0';
+ PutLine0(x, y, buffer);
+}
+
+
+/*----------------------------------------------------------------------
+ Output a UTF-8 line to the screen, centered
+
+ Input: Line number to print on, string to output
+
+ Result: String is output to screen
+ Returns column number line is output on
+ ----------------------------------------------------------------------*/
+int
+Centerline(int line, char *string)
+{
+ int width, col;
+
+ width = (int) utf8_width(string);
+
+ if (width > ps_global->ttyo->screen_cols)
+ col = 0;
+ else
+ col = (ps_global->ttyo->screen_cols - width) / 2;
+
+ PutLine0(line, col, string);
+
+ return(col);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Clear specified line on the screen
+
+ Result: The line is blanked and the cursor is left at column 0.
+
+ ----*/
+void
+ClearLine(int n)
+{
+ if(ps_global->in_init_seq)
+ return;
+
+ MoveCursor(n, 0);
+ CleartoEOLN();
+}
+
+
+
+/*----------------------------------------------------------------------
+ Clear specified lines on the screen
+
+ Result: The lines starting at 'x' and ending at 'y' are blanked
+ and the cursor is left at row 'x', column 0
+
+ ----*/
+void
+ClearLines(int x, int y)
+{
+ int i;
+
+ for(i = x; i <= y; i++)
+ ClearLine(i);
+
+ MoveCursor(x, 0);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Indicate to the screen painting here that the position of the cursor
+ has been disturbed and isn't where these functions might think.
+ ----*/
+void
+clear_cursor_pos(void)
+{
+ _line = FARAWAY;
+ _col = FARAWAY;
+}
+
+
+/*----------------------------------------------------------------------
+ Write a character to the screen, keeping track of cursor position
+
+ Args: ch -- character to output. The stream of characters coming to
+ this function is expected to be UTF-8. State is kept between
+ calls in order to collect up the octets needed for a single
+ Unicode character.
+
+ Result: character output
+ cursor position variables updated
+ ----*/
+void
+Writechar(unsigned int ch, int new_esc_len)
+{
+ static unsigned char cbuf[6];
+ static unsigned char *cbufp = cbuf;
+
+ if(cbufp < cbuf+sizeof(cbuf)){
+ unsigned char *inputp;
+ unsigned long remaining_octets;
+ UCS ucs;
+
+ *cbufp++ = (unsigned char) ch;
+ inputp = cbuf;
+ remaining_octets = (cbufp - cbuf) * sizeof(unsigned char);
+ ucs = (UCS) utf8_get(&inputp, &remaining_octets);
+
+ switch(ucs){
+ case U8G_ENDSTRG: /* incomplete character, wait */
+ case U8G_ENDSTRI: /* incomplete character, wait */
+ break;
+
+ default:
+ if(ucs & U8G_ERROR || ucs == UBOGON){
+ /*
+ * None of these cases is supposed to happen. If it
+ * does happen then the input stream isn't UTF-8
+ * so something is wrong. Treat each character in the
+ * input buffer as a separate error character and
+ * print a '?' for each.
+ */
+ for(inputp = cbuf; inputp < cbufp; inputp++){
+ int width = 0;
+
+ if(_col + width <= ps_global->ttyo->screen_cols){
+ Writewchar('?');
+ width++;
+ }
+ }
+
+ cbufp = cbuf; /* start over */
+ }
+ else{
+
+ /* got a good character */
+ Writewchar(ucs);
+
+ /* update the input buffer */
+ if(inputp >= cbufp) /* this should be the case */
+ cbufp = cbuf;
+ else{ /* extra chars for some reason? */
+ unsigned char *q, *newcbufp;
+
+ newcbufp = (cbufp - inputp) + cbuf;
+ q = cbuf;
+ while(inputp < cbufp)
+ *q++ = *inputp++;
+
+ cbufp = newcbufp;
+ }
+ }
+
+ break;
+ }
+ }
+ else{ /* error */
+ Writewchar('?');
+ cbufp = cbuf; /* start over */
+ }
+}
diff --git a/alpine/osdep/termout.gen.h b/alpine/osdep/termout.gen.h
new file mode 100644
index 00000000..2aff4b37
--- /dev/null
+++ b/alpine/osdep/termout.gen.h
@@ -0,0 +1,54 @@
+/*
+ * $Id: termout.gen.h 769 2007-10-24 00:15:40Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_TERMOUT_GEN_INCLUDED
+#define PINE_OSDEP_TERMOUT_GEN_INCLUDED
+
+
+extern int _line;
+extern int _col;
+
+
+/* exported prototypes */
+void PutLine0(int, int, register char *);
+void PutLine0n8b(int, int, register char *, int, HANDLE_S *);
+void PutLine1(int, int, char *, void *);
+void PutLine2(int, int, char *, void *, void *);
+void PutLine3(int, int, char *, void *, void *, void *);
+void PutLine4(int, int, char *, void *, void *, void *, void *);
+void PutLine5(int, int, char *, void *, void *, void *, void *, void *);
+int Centerline(int, char *);
+void ClearLine(int);
+void ClearLines(int, int);
+void CleartoEOLN(void);
+void ClearScreen(void);
+void clear_cursor_pos(void);
+void Writechar(unsigned int, int);
+void Write_to_screen(char *);
+void Write_to_screen_n(char *, int);
+void init_screen(void);
+void end_screen(char *, int);
+int config_screen(struct ttyo **);
+void MoveCursor(int, int);
+void Writewchar(UCS);
+void icon_text(char *, int);
+int get_windsize(struct ttyo *);
+int BeginScroll(int, int);
+void EndScroll(void);
+int ScrollRegion(int);
+
+
+#endif /* PINE_OSDEP_TERMOUT_GEN_INCLUDED */
diff --git a/alpine/osdep/termout.unx.c b/alpine/osdep/termout.unx.c
new file mode 100644
index 00000000..faf8c7f9
--- /dev/null
+++ b/alpine/osdep/termout.unx.c
@@ -0,0 +1,1002 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: termout.unx.c 955 2008-03-06 23:52:36Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2008 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+#include <system.h>
+#include <general.h>
+
+#include "../../c-client/mail.h" /* for MAILSTREAM and friends */
+#include "../../c-client/osdep.h"
+#include "../../c-client/rfc822.h" /* for soutr_t and such */
+#include "../../c-client/misc.h" /* for cpystr proto */
+#include "../../c-client/utf8.h" /* for CHARSET and such*/
+#include "../../c-client/imap4r1.h"
+
+#include "../../pith/osdep/color.h"
+
+#include "../../pith/debug.h"
+#include "../../pith/conf.h"
+#include "../../pith/newmail.h"
+#include "../../pith/charconv/utf8.h"
+
+#include "../../pico/estruct.h"
+#include "../../pico/pico.h"
+#include "../../pico/edef.h"
+#include "../../pico/efunc.h"
+#include "../../pico/osdep/color.h"
+
+#include "../status.h"
+#include "../keymenu.h"
+#include "../titlebar.h"
+
+#include "termout.gen.h"
+#include "termout.unx.h"
+
+
+/*======================================================================
+ Routines for painting the screen
+ - figure out what the terminal type is
+ - deal with screen size changes
+ - save special output sequences
+ - the usual screen clearing, cursor addressing and scrolling
+
+
+ This library gives programs the ability to easily access the
+ termcap information and write screen oriented and raw input
+ programs. The routines can be called as needed, except that
+ to use the cursor / screen routines there must be a call to
+ InitScreen() first. The 'Raw' input routine can be used
+ independently, however. (Elm comment)
+
+ Not sure what the original source of this code was. It got to be
+ here as part of ELM. It has been changed significantly from the
+ ELM version to be more robust in the face of inconsistent terminal
+ autowrap behaviour. Also, the unused functions were removed, it was
+ made to pay attention to the window size, and some code was made nicer
+ (in my opinion anyways). It also outputs the terminal initialization
+ strings and provides for minimal scrolling and detects terminals
+ with out enough capabilities. (Pine comment, 1990)
+
+
+This code used to pay attention to the "am" auto margin and "xn"
+new line glitch fields, but they were so often incorrect because many
+terminals can be configured to do either that we've taken it out. It
+now assumes it dosn't know where the cursor is after outputing in the
+80th column.
+*/
+
+
+static int _lines, _columns;
+
+
+/*
+ * Internal prototypes
+ */
+static int outchar(int);
+static void moveabsolute(int, int);
+static void CursorUp(int);
+static void CursorDown(int);
+static void CursorLeft(int);
+static void CursorRight(int);
+
+
+extern char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
+ *_setinverse, *_clearinverse,
+ *_cleartoeoln, *_cleartoeos,
+ *_startinsert, *_endinsert, *_insertchar, *_deletechar,
+ *_deleteline, *_insertline,
+ *_scrollregion, *_scrollup, *_scrolldown,
+ *_termcap_init, *_termcap_end;
+extern char term_name[];
+extern int _tlines, _tcolumns, _bce;
+
+static enum {NoScroll,UseScrollRegion,InsertDelete} _scrollmode;
+
+extern int tputs(char *, int, int (*)(int));
+extern char *tgoto(char *, int, int);
+
+
+
+/*----------------------------------------------------------------------
+ Initialize the screen for output, set terminal type, etc
+
+ Args: tt -- Pointer to variable to store the tty output structure.
+
+ Result: terminal size is discovered and set in pine state
+ termcap entry is fetched and stored
+ make sure terminal has adequate capabilites
+ evaluate scrolling situation
+ returns status of indicating the state of the screen/termcap entry
+
+ Returns:
+ -1 indicating no terminal name associated with this shell,
+ -2..-n No termcap for this terminal type known
+ -3 Can't open termcap file
+ -4 Terminal not powerful enough - missing clear to eoln or screen
+ or cursor motion
+ ----*/
+int
+config_screen(struct ttyo **tt)
+{
+ struct ttyo *ttyo;
+ int err;
+
+ ttyo = (struct ttyo *)fs_get(sizeof (struct ttyo));
+
+ _line = 0; /* where are we right now?? */
+ _col = 0; /* assume zero, zero... */
+
+ /*
+ * This is an ugly hack to let vtterminalinfo know it's being called
+ * from pine.
+ */
+ Pmaster = (PICO *)1;
+ if((err = vtterminalinfo(F_ON(F_TCAP_WINS, ps_global))) != 0)
+ return(err);
+
+ Pmaster = NULL;
+
+ if(_tlines <= 0)
+ _lines = DEFAULT_LINES_ON_TERMINAL;
+ else
+ _lines = _tlines;
+
+ if(_tcolumns <= 0)
+ _columns = DEFAULT_COLUMNS_ON_TERMINAL;
+ else
+ _columns = _tcolumns;
+
+ get_windsize(ttyo);
+
+ ttyo->header_rows = 2;
+ ttyo->footer_rows = 3;
+
+ /*---- Make sure this terminal has the capability.
+ All we need is cursor address, clear line, and
+ reverse video.
+ ---*/
+ if(_moveto == NULL || _cleartoeoln == NULL ||
+ _setinverse == NULL || _clearinverse == NULL) {
+ return(-4);
+ }
+
+ dprint((1, "Terminal type: %s\n", term_name ? term_name : "?"));
+
+ /*------ Figure out scrolling mode -----*/
+ if(_scrollregion != NULL && _scrollregion[0] != '\0' &&
+ _scrollup != NULL && _scrollup[0] != '\0'){
+ _scrollmode = UseScrollRegion;
+ } else if(_insertline != NULL && _insertline[0] != '\0' &&
+ _deleteline != NULL && _deleteline[0] != '\0') {
+ _scrollmode = InsertDelete;
+ } else {
+ _scrollmode = NoScroll;
+ }
+ dprint((7, "Scroll mode: %s\n",
+ _scrollmode==NoScroll ? "No Scroll" :
+ _scrollmode==InsertDelete ? "InsertDelete" : "Scroll Regions"));
+
+ if (!_left) {
+ _left = "\b";
+ }
+
+ *tt = ttyo;
+
+ return(0);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Initialize the screen with the termcap string
+ ----*/
+void
+init_screen(void)
+{
+ if(_termcap_init) /* init using termcap's rule */
+ tputs(_termcap_init, 1, outchar);
+
+ /* and make sure there are no scrolling surprises! */
+ BeginScroll(0, ps_global->ttyo->screen_rows - 1);
+
+ pico_toggle_color(0);
+ switch(ps_global->color_style){
+ case COL_NONE:
+ case COL_TERMDEF:
+ pico_set_color_options(pico_trans_color() ? COLOR_TRANS_OPT : 0);
+ break;
+ case COL_ANSI8:
+ pico_set_color_options(COLOR_ANSI8_OPT|COLOR_TRANS_OPT);
+ break;
+ case COL_ANSI16:
+ pico_set_color_options(COLOR_ANSI16_OPT|COLOR_TRANS_OPT);
+ break;
+ case COL_ANSI256:
+ pico_set_color_options(COLOR_ANSI256_OPT|COLOR_TRANS_OPT);
+ break;
+ }
+
+ if(ps_global->color_style != COL_NONE)
+ pico_toggle_color(1);
+
+ /* set colors */
+ if(pico_usingcolor()){
+ if(ps_global->VAR_NORM_FORE_COLOR)
+ pico_nfcolor(ps_global->VAR_NORM_FORE_COLOR);
+
+ if(ps_global->VAR_NORM_BACK_COLOR)
+ pico_nbcolor(ps_global->VAR_NORM_BACK_COLOR);
+
+ if(ps_global->VAR_REV_FORE_COLOR)
+ pico_rfcolor(ps_global->VAR_REV_FORE_COLOR);
+
+ if(ps_global->VAR_REV_BACK_COLOR)
+ pico_rbcolor(ps_global->VAR_REV_BACK_COLOR);
+
+ pico_set_normal_color();
+ }
+
+ /* and make sure icon text starts out consistent */
+ icon_text(NULL, IT_NEWMAIL);
+ fflush(stdout);
+}
+
+
+
+
+/*----------------------------------------------------------------------
+ Get the current window size
+
+ Args: ttyo -- pointer to structure to store window size in
+
+ NOTE: we don't override the given values unless we know better
+ ----*/
+int
+get_windsize(struct ttyo *ttyo)
+{
+#if defined(SIGWINCH) && defined(TIOCGWINSZ)
+ struct winsize win;
+
+ /*
+ * Get the window size from the tty driver. If we can't fish it from
+ * stdout (pine's output is directed someplace else), try stdin (which
+ * *must* be associated with the terminal; see init_tty_driver)...
+ */
+ if(ioctl(1, TIOCGWINSZ, &win) >= 0 /* 1 is stdout */
+ || ioctl(0, TIOCGWINSZ, &win) >= 0){ /* 0 is stdin */
+ if(win.ws_row)
+ _lines = MIN(win.ws_row, MAX_SCREEN_ROWS);
+
+ if(win.ws_col)
+ _columns = MIN(win.ws_col, MAX_SCREEN_COLS);
+
+ dprint((2, "new win size -----<%d %d>------\n",
+ _lines, _columns));
+ }
+ else{
+ /* Depending on the OS, the ioctl() may have failed because
+ of a 0 rows, 0 columns setting. That happens on DYNIX/ptx 1.3
+ (with a kernel patch that happens to involve the negotiation
+ of window size in the telnet streams module.) In this case
+ the error is EINVARG. Leave the default settings. */
+ dprint((1, "ioctl(TIOCWINSZ) failed :%s\n",
+ error_description(errno)));
+ }
+#endif
+
+ ttyo->screen_cols = MIN(_columns, MAX_SCREEN_COLS);
+ ttyo->screen_rows = MIN(_lines, MAX_SCREEN_ROWS);
+ return(0);
+}
+
+
+/*----------------------------------------------------------------------
+ End use of the screen.
+ Print status message, if any.
+ Flush status messages.
+ ----*/
+void
+end_screen(char *message, int exit_val)
+{
+ int footer_rows_was_one = 0;
+
+ if(!panicking()){
+
+ dprint((9, "end_screen called\n"));
+
+ if(FOOTER_ROWS(ps_global) == 1){
+ footer_rows_was_one++;
+ FOOTER_ROWS(ps_global) = 3;
+ mark_status_unknown();
+ }
+
+ flush_status_messages(exit_val ? 0 : 1);
+ blank_keymenu(_lines - 2, 0);
+ MoveCursor(_lines - 2, 0);
+ }
+
+ /* unset colors */
+ if(pico_usingcolor())
+ pico_endcolor();
+
+ if(_termcap_end != NULL)
+ tputs(_termcap_end, 1, outchar);
+
+ if(!panicking()){
+
+ if(message){
+ printf("%s\r\n", message);
+ }
+
+ if(F_ON(F_ENABLE_XTERM_NEWMAIL, ps_global) && getenv("DISPLAY"))
+ icon_text("xterm", IT_NEWMAIL);
+
+ fflush(stdout);
+
+ if(footer_rows_was_one){
+ FOOTER_ROWS(ps_global) = 1;
+ mark_status_unknown();
+ }
+ }
+}
+
+
+
+/*----------------------------------------------------------------------
+ Clear the terminal screen
+
+ Result: The screen is cleared
+ internal cursor position set to 0,0
+ ----*/
+void
+ClearScreen(void)
+{
+ _line = 0; /* clear leaves us at top... */
+ _col = 0;
+
+ if(ps_global->in_init_seq)
+ return;
+
+ mark_status_unknown();
+ mark_keymenu_dirty();
+ mark_titlebar_dirty();
+
+ /*
+ * If the terminal doesn't have back color erase, then we have to
+ * erase manually to preserve the background color.
+ */
+ if(pico_usingcolor() && (!_bce || !_clearscreen)){
+ ClearLines(0, _lines-1);
+ MoveCursor(0, 0);
+ }
+ else if(_clearscreen){
+ tputs(_clearscreen, 1, outchar);
+ moveabsolute(0, 0); /* some clearscreens don't move correctly */
+ }
+}
+
+
+/*----------------------------------------------------------------------
+ Internal move cursor to absolute position
+
+ Args: col -- column to move cursor to
+ row -- row to move cursor to
+
+ Result: cursor is moved (variables, not updates)
+ ----*/
+
+static void
+moveabsolute(int col, int row)
+{
+
+ char *stuff, *tgoto();
+
+ stuff = tgoto(_moveto, col, row);
+ tputs(stuff, 1, outchar);
+}
+
+
+/*----------------------------------------------------------------------
+ Move the cursor to the row and column number
+ Args: row number
+ column number
+
+ Result: Cursor moves
+ internal position updated
+ ----*/
+void
+MoveCursor(int row, int col)
+{
+ /** move cursor to the specified row column on the screen.
+ 0,0 is the top left! **/
+
+ int scrollafter = 0;
+
+ /* we don't want to change "rows" or we'll mangle scrolling... */
+
+ if(ps_global->in_init_seq)
+ return;
+
+ if (col < 0)
+ col = 0;
+ if (col >= ps_global->ttyo->screen_cols)
+ col = ps_global->ttyo->screen_cols - 1;
+ if (row < 0)
+ row = 0;
+ if (row > ps_global->ttyo->screen_rows) {
+ if (col == 0)
+ scrollafter = row - ps_global->ttyo->screen_rows;
+ row = ps_global->ttyo->screen_rows;
+ }
+
+ if (!_moveto)
+ return;
+
+ if (_col >= ps_global->ttyo->screen_cols)
+ _col = ps_global->ttyo->screen_cols - 1;
+
+ if (row == _line) {
+ if (col == _col)
+ return; /* already there! */
+
+ else if (abs(col - _col) < 5) { /* within 5 spaces... */
+ if (col > _col && _right)
+ CursorRight(col - _col);
+ else if (col < _col && _left)
+ CursorLeft(_col - col);
+ else
+ moveabsolute(col, row);
+ }
+ else /* move along to the new x,y loc */
+ moveabsolute(col, row);
+ }
+ else if (col == _col && abs(row - _line) < 5) {
+ if (row < _line && _up)
+ CursorUp(_line - row);
+ else if (_line > row && _down)
+ CursorDown(row - _line);
+ else
+ moveabsolute(col, row);
+ }
+ else if (_line == row-1 && col == 0) {
+ putchar('\n'); /* that's */
+ putchar('\r'); /* easy! */
+ }
+ else
+ moveabsolute(col, row);
+
+ _line = row; /* to ensure we're really there... */
+ _col = col;
+
+ if (scrollafter) {
+ while (scrollafter--) {
+ putchar('\n');
+ putchar('\r');
+
+ }
+ }
+
+ return;
+}
+
+
+
+/*----------------------------------------------------------------------
+ Newline, move the cursor to the start of next line
+
+ Result: Cursor moves
+ ----*/
+void
+NewLine(void)
+{
+ /** move the cursor to the beginning of the next line **/
+
+ Writechar('\n', 0);
+ Writechar('\r', 0);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Move cursor up n lines with terminal escape sequence
+
+ Args: n -- number of lines to go up
+
+ Result: cursor moves,
+ internal position updated
+
+ Only for ttyout use; not outside callers
+ ----*/
+static void
+CursorUp(int n)
+{
+ /** move the cursor up 'n' lines **/
+ /** Calling function must check that _up is not null before calling **/
+
+ _line = (_line-n > 0? _line - n: 0); /* up 'n' lines... */
+
+ while (n-- > 0)
+ tputs(_up, 1, outchar);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Move cursor down n lines with terminal escape sequence
+
+ Arg: n -- number of lines to go down
+
+ Result: cursor moves,
+ internal position updated
+
+ Only for ttyout use; not outside callers
+ ----*/
+static void
+CursorDown(int n)
+{
+ /** move the cursor down 'n' lines **/
+ /** Caller must check that _down is not null before calling **/
+
+ _line = (_line+n < ps_global->ttyo->screen_rows ? _line + n
+ : ps_global->ttyo->screen_rows);
+ /* down 'n' lines... */
+
+ while (n-- > 0)
+ tputs(_down, 1, outchar);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Move cursor left n lines with terminal escape sequence
+
+ Args: n -- number of lines to go left
+
+ Result: cursor moves,
+ internal position updated
+
+ Only for ttyout use; not outside callers
+ ----*/
+static void
+CursorLeft(int n)
+{
+ /** move the cursor 'n' characters to the left **/
+ /** Caller must check that _left is not null before calling **/
+
+ _col = (_col - n> 0? _col - n: 0); /* left 'n' chars... */
+
+ while (n-- > 0)
+ tputs(_left, 1, outchar);
+}
+
+
+/*----------------------------------------------------------------------
+ Move cursor right n lines with terminal escape sequence
+
+ Args: number of lines to go right
+
+ Result: cursor moves,
+ internal position updated
+
+ Only for ttyout use; not outside callers
+ ----*/
+static void
+CursorRight(int n)
+{
+ /** move the cursor 'n' characters to the right (nondestructive) **/
+ /** Caller must check that _right is not null before calling **/
+
+ _col = (_col+n < ps_global->ttyo->screen_cols? _col + n :
+ ps_global->ttyo->screen_cols); /* right 'n' chars... */
+
+ while (n-- > 0)
+ tputs(_right, 1, outchar);
+
+}
+
+
+/*----------------------------------------------------------------------
+ Go into scrolling mode, that is set scrolling region if applicable
+
+ Args: top -- top line of region to scroll
+ bottom -- bottom line of region to scroll
+ (These are zero-origin numbers)
+
+ Result: either set scrolling region or
+ save values for later scrolling
+ returns -1 if we can't scroll
+
+ Unfortunately this seems to leave the cursor in an unpredictable place
+ at least the manuals don't say where, so we force it here.
+-----*/
+static int __t, __b;
+
+int
+BeginScroll(int top, int bottom)
+{
+ char *stuff;
+
+ if(_scrollmode == NoScroll)
+ return(-1);
+
+ __t = top;
+ __b = bottom;
+ if(_scrollmode == UseScrollRegion){
+ stuff = tgoto(_scrollregion, bottom, top);
+ tputs(stuff, 1, outchar);
+ /*-- a location very far away to force a cursor address --*/
+ _line = FARAWAY;
+ _col = FARAWAY;
+ }
+ return(0);
+}
+
+
+
+/*----------------------------------------------------------------------
+ End scrolling -- clear scrolling regions if necessary
+
+ Result: Clear scrolling region on terminal
+ -----*/
+void
+EndScroll(void)
+{
+ if(_scrollmode == UseScrollRegion && _scrollregion != NULL){
+ /* Use tgoto even though we're not cursor addressing because
+ the format of the capability is the same.
+ */
+ char *stuff = tgoto(_scrollregion, ps_global->ttyo->screen_rows -1, 0);
+ tputs(stuff, 1, outchar);
+ /*-- a location very far away to force a cursor address --*/
+ _line = FARAWAY;
+ _col = FARAWAY;
+ }
+}
+
+
+/* ----------------------------------------------------------------------
+ Scroll the screen using insert/delete or scrolling regions
+
+ Args: lines -- number of lines to scroll, positive forward
+
+ Result: Screen scrolls
+ returns 0 if scroll succesful, -1 if not
+
+ positive lines goes foward (new lines come in at bottom
+ Leaves cursor at the place to insert put new text
+
+ 0,0 is the upper left
+ -----*/
+int
+ScrollRegion(int lines)
+{
+ int l;
+
+ if(lines == 0)
+ return(0);
+
+ if(_scrollmode == UseScrollRegion) {
+ if(lines > 0) {
+ MoveCursor(__b, 0);
+ for(l = lines ; l > 0 ; l--)
+ tputs((_scrolldown == NULL || _scrolldown[0] =='\0') ? "\n" :
+ _scrolldown, 1, outchar);
+ } else {
+ MoveCursor(__t, 0);
+ for(l = -lines; l > 0; l--)
+ tputs(_scrollup, 1, outchar);
+ }
+ } else if(_scrollmode == InsertDelete) {
+ if(lines > 0) {
+ MoveCursor(__t, 0);
+ for(l = lines; l > 0; l--)
+ tputs(_deleteline, 1, outchar);
+ MoveCursor(__b, 0);
+ for(l = lines; l > 0; l--)
+ tputs(_insertline, 1, outchar);
+ } else {
+ for(l = -lines; l > 0; l--) {
+ MoveCursor(__b, 0);
+ tputs(_deleteline, 1, outchar);
+ MoveCursor(__t, 0);
+ tputs(_insertline, 1, outchar);
+ }
+ }
+ } else {
+ return(-1);
+ }
+ fflush(stdout);
+ return(0);
+}
+
+
+void
+Writewchar(UCS ucs)
+{
+ if(ps_global->in_init_seq /* silent */
+ || (F_ON(F_BLANK_KEYMENU, ps_global) /* or bottom, */
+ /* right cell */
+ && _line + 1 == ps_global->ttyo->screen_rows
+ && _col + 1 == ps_global->ttyo->screen_cols))
+ return;
+
+
+ if(ucs == LINE_FEED || ucs == RETURN || ucs == BACKSPACE || ucs == BELL || ucs == TAB){
+ switch(ucs){
+ case LINE_FEED:
+ /*-- Don't have to watch out for auto wrap or newline glitch
+ because we never let it happen. See below
+ ---*/
+ putchar('\n');
+ _line = MIN(_line+1,ps_global->ttyo->screen_rows);
+ break;
+
+ case RETURN : /* move to column 0 */
+ putchar('\r');
+ _col = 0;
+ break;
+
+ case BACKSPACE : /* move back a space if not in column 0 */
+ if(_col != 0) {
+ putchar('\b');
+ _col--;
+ } /* else BACKSPACE does nothing */
+
+ break;
+
+ case BELL : /* ring the bell but don't advance _col */
+ putchar((int) ucs);
+ break;
+
+ case TAB : /* if a tab, output it */
+ do /* BUG? ignores tty driver's spacing */
+ putchar(' ');
+ /* fix from Eduardo Chappa, have to increment _col once more */
+ while(_col < ps_global->ttyo->screen_cols
+ && ((++_col)&0x07) != 0);
+ break;
+ }
+ }
+ else{
+ unsigned char obuf[MAX(MB_LEN_MAX,32)];
+ int i, width = 0, outchars = 0, printable_ascii = 0;
+
+ if(ucs < 0x80 && isprint((unsigned char) ucs)){
+ printable_ascii++; /* efficiency shortcut */
+ width = 1;
+ }
+ else
+ width = wcellwidth(ucs);
+
+ if(width < 0){
+ /*
+ * This happens when we have a Unicode character that
+ * we aren't able to print in our locale. For example,
+ * if the locale is setup with the terminal
+ * expecting ISO-8859-1 characters then there are
+ * lots of Unicode characters that can't be printed.
+ * Print a '?' instead.
+ */
+ width = 1;
+ obuf[outchars++] = '?';
+ }
+ else if(_col + width > ps_global->ttyo->screen_cols){
+ /*
+ * Hopefully this won't happen. The
+ * character overflows the right edge because it
+ * is a double wide and we're in last column.
+ * Fill with spaces instead and toss the
+ * character.
+ *
+ * Put a > in the right column to show we tried to write
+ * past the end.
+ */
+ while(outchars < ps_global->ttyo->screen_cols - _col - 1)
+ obuf[outchars++] = ' ';
+
+ obuf[outchars++] = '>';
+
+ /*
+ * In case last time through wrote in the last column and
+ * caused an autowrap, reposition cursor.
+ */
+ if(_col >= ps_global->ttyo->screen_cols)
+ moveabsolute(ps_global->ttyo->screen_cols-1, _line);
+ }
+ else{
+ /*
+ * Convert the ucs into the multibyte
+ * character that corresponds to the
+ * ucs in the users locale.
+ */
+ if(printable_ascii)
+ obuf[outchars++] = (unsigned char) ucs;
+ else{
+ outchars = wtomb((char *) obuf, ucs);
+ if(outchars < 0){
+ width = 1;
+ obuf[0] = '?';
+ outchars = 1;
+ }
+ }
+ }
+
+ _col += width;
+ for(i = 0; i < outchars; i++)
+ putchar(obuf[i]);
+ }
+
+ /*
+ * We used to wrap by moving to the next line and making _col = 0
+ * when we went past the end. We don't believe that this is useful
+ * anymore. If we wrap it is unintentional. Instead, stay at the
+ * end of the line. We need to be a little careful because we're
+ * moving to a different place than _col is set to, but since _col
+ * is off the right edge, it should be ok.
+ */
+ if(_col >= ps_global->ttyo->screen_cols) {
+ _col = ps_global->ttyo->screen_cols;
+ moveabsolute(ps_global->ttyo->screen_cols-1, _line);
+ }
+}
+
+
+void
+Write_to_screen(char *string) /* UNIX */
+
+{
+ while(*string)
+ Writechar((unsigned char) *string++, 0);
+}
+
+
+/*----------------------------------------------------------------------
+ Write no more than n chars of string to screen at current cursor position
+
+ Args: string -- string to be output
+ n -- number of chars to output
+
+ Result: String written to the screen
+ ----*/
+void
+Write_to_screen_n(char *string, int n) /* UNIX */
+
+
+{
+ while(n-- && *string)
+ Writechar((unsigned char) *string++, 0);
+}
+
+
+/*----------------------------------------------------------------------
+ Clear screen to end of line on current line
+
+ Result: Line is cleared
+ ----*/
+void
+CleartoEOLN(void)
+{
+ int c, starting_col, starting_line;
+ char *last_bg_color;
+
+ /*
+ * If the terminal doesn't have back color erase, then we have to
+ * erase manually to preserve the background color.
+ */
+ if(pico_usingcolor() && (!_bce || !_cleartoeoln)){
+ starting_col = _col;
+ starting_line = _line;
+ last_bg_color = pico_get_last_bg_color();
+ pico_set_nbg_color();
+ for(c = _col; c < _columns; c++)
+ Writechar(' ', 0);
+
+ MoveCursor(starting_line, starting_col);
+ if(last_bg_color){
+ (void)pico_set_bg_color(last_bg_color);
+ fs_give((void **)&last_bg_color);
+ }
+ }
+ else if(_cleartoeoln)
+ tputs(_cleartoeoln, 1, outchar);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Clear screen to end of screen from current point
+
+ Result: screen is cleared
+ ----*/
+void
+CleartoEOS(void)
+{
+ int starting_col, starting_line;
+
+ /*
+ * If the terminal doesn't have back color erase, then we have to
+ * erase manually to preserve the background color.
+ */
+ if(pico_usingcolor() && (!_bce || !_cleartoeos)){
+ starting_col = _col;
+ starting_line = _line;
+ CleartoEOLN();
+ ClearLines(_line+1, _lines-1);
+ MoveCursor(starting_line, starting_col);
+ }
+ else if(_cleartoeos)
+ tputs(_cleartoeos, 1, outchar);
+}
+
+
+
+/*----------------------------------------------------------------------
+ function to output character used by termcap
+
+ Args: c -- character to output
+
+ Result: character output to screen via stdio
+ ----*/
+int
+outchar(int c)
+{
+ /** output the given character. From tputs... **/
+ /** Note: this CANNOT be a macro! **/
+
+ return(putc((unsigned char)c, stdout));
+}
+
+
+
+/*----------------------------------------------------------------------
+ function to output string such that it becomes icon text
+
+ Args: s -- string to write
+
+ Result: string indicated become our "icon" text
+ ----*/
+void
+icon_text(char *s, int type)
+{
+ static enum {ukn, yes, no} xterm;
+ char *str, *converted, *use_this;
+
+ if(xterm == ukn)
+ xterm = (getenv("DISPLAY") != NULL) ? yes : no;
+
+ if(F_ON(F_ENABLE_XTERM_NEWMAIL,ps_global) && xterm == yes){
+ fputs("\033]0;", stdout);
+
+ str = s ? s : ps_global->pine_name;
+ converted = convert_to_locale(str);
+ use_this = converted ? converted : str;
+
+ fputs(use_this, stdout);
+
+ fputs("\007", stdout);
+ fputs("\033]1;", stdout);
+
+ fputs(use_this, stdout);
+
+ fputs("\007", stdout);
+ fflush(stdout);
+
+ if(converted)
+ fs_give((void **) &converted);
+ }
+}
+
+
diff --git a/alpine/osdep/termout.unx.h b/alpine/osdep/termout.unx.h
new file mode 100644
index 00000000..4d9d1b5c
--- /dev/null
+++ b/alpine/osdep/termout.unx.h
@@ -0,0 +1,24 @@
+/*
+ * $Id: termout.unx.h 769 2007-10-24 00:15:40Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_TERMOUT_UNX_INCLUDED
+#define PINE_OSDEP_TERMOUT_UNX_INCLUDED
+
+
+/* exported prototypes */
+
+
+#endif /* PINE_OSDEP_TERMOUT_UNX_INCLUDED */
diff --git a/alpine/osdep/termout.win b/alpine/osdep/termout.win
new file mode 100644
index 00000000..f3f027ee
--- /dev/null
+++ b/alpine/osdep/termout.win
@@ -0,0 +1,127 @@
+#line 2 "osdep/termout.win"
+
+
+
+
+
+/*----------------------------------------------------------------------
+ End use of the screen.
+ ----------------------------------------------------------------------*/
+
+
+
+
+/*----------------------------------------------------------------------
+ Newline, move the cursor to the start of next line
+
+ Input: none
+
+ Result: Cursor moves
+ ----------------------------------------------------------------------*/
+void
+NewLine()
+{
+ /** move the cursor to the beginning of the next line **/
+
+ MoveCursor(_line+1, 0);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Insert character on screen pushing others right
+
+ Input: character to output
+ termcap escape sequences
+
+ Result: charcter is inserted if possible
+ return -1 if it can't be done
+ ----------------------------------------------------------------------*/
+InsertChar(c)
+ int c;
+{
+ mswin_inschar (c);
+ return (0);
+}
+
+
+/*----------------------------------------------------------------------
+ Delete n characters from line, sliding rest of line left
+
+ Input: number of characters to delete
+ termcap escape sequences
+
+ Result: characters deleted on screen
+ returns -1 if it wasn't done
+ ----------------------------------------------------------------------*/
+DeleteChar(n)
+ int n;
+{
+ char c;
+ int oc; /* original column */
+
+ mswin_delchar ();
+ return(0);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Go into scrolling mode, that is set scrolling region if applicable
+
+ Input: top line of region to scroll
+ bottom line of region to scroll
+
+ Result: either set scrolling region or
+ save values for later scrolling
+ returns -1 if we can't scroll
+
+ Unfortunately this seems to leave the cursor in an unpredictable place
+ at least the manuals don't say were, so we force it here.
+----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------
+ End scrolling -- clear scrolling regions if necessary
+
+ Input: none
+
+ Result: Clear scrolling region on terminal
+ ----------------------------------------------------------------------*/
+
+
+/* ----------------------------------------------------------------------
+ Scroll the screen using insert/delete or scrolling regions
+
+ Input: number of lines to scroll, positive forward
+
+ Result: Screen scrolls
+ returns 0 if scroll succesful, -1 if not
+
+ positive lines goes foward (new lines come in at bottom
+ Leaves cursor at the place to insert put new text
+
+ 0,0 is the upper left
+ ----------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------
+ Clear screen to end of screen from current point
+
+ Input: none
+
+ Result: screen is cleared
+ ----------------------------------------------------------------------*/
+void
+CleartoEOS() /* DOS */
+{
+ mswin_eeop();
+}
+
+
diff --git a/alpine/osdep/termout.wnt.c b/alpine/osdep/termout.wnt.c
new file mode 100644
index 00000000..fae661aa
--- /dev/null
+++ b/alpine/osdep/termout.wnt.c
@@ -0,0 +1,1862 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: termout.unx.c 159 2006-10-02 22:00:13Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+#include <system.h>
+#include <general.h>
+
+#include "../../c-client/mail.h" /* for MAILSTREAM and friends */
+#include "../../c-client/osdep.h"
+#include "../../c-client/rfc822.h" /* for soutr_t and such */
+#include "../../c-client/misc.h" /* for cpystr proto */
+#include "../../c-client/utf8.h" /* for CHARSET and such*/
+#include "../../c-client/imap4r1.h"
+
+#include "../../pith/osdep/color.h"
+
+#include "../../pith/charconv/filesys.h"
+
+#include "../../pith/debug.h"
+#include "../../pith/conf.h"
+#include "../../pith/newmail.h"
+
+#include "../../pico/estruct.h"
+#include "../../pico/pico.h"
+#include "../../pico/keydefs.h"
+
+#include "../../pico/osdep/mswin.h"
+#include "../../pico/osdep/color.h"
+
+#include "../flagmaint.h"
+#include "../status.h"
+#include "../keymenu.h"
+#include "../titlebar.h"
+
+#include "termout.gen.h"
+#include "termout.wnt.h"
+
+/*======================================================================
+ Routines for painting the screen
+ - figure out what the terminal type is
+ - deal with screen size changes
+ - save special output sequences
+ - the usual screen clearing, cursor addressing and scrolling
+
+
+ This library gives programs the ability to easily access the
+ termcap information and write screen oriented and raw input
+ programs. The routines can be called as needed, except that
+ to use the cursor / screen routines there must be a call to
+ InitScreen() first. The 'Raw' input routine can be used
+ independently, however. (Elm comment)
+
+ Not sure what the original source of this code was. It got to be
+ here as part of ELM. It has been changed significantly from the
+ ELM version to be more robust in the face of inconsistent terminal
+ autowrap behaviour. Also, the unused functions were removed, it was
+ made to pay attention to the window size, and some code was made nicer
+ (in my opinion anyways). It also outputs the terminal initialization
+ strings and provides for minimal scrolling and detects terminals
+ with out enough capabilities. (Pine comment, 1990)
+
+*/
+
+#define PUTLINE_BUFLEN 256
+
+static int _lines, _columns;
+
+BOOL CALLBACK __export
+args_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+BOOL CALLBACK __export
+login_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+BOOL CALLBACK __export
+flag_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+BOOL CALLBACK __export
+sort_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+BOOL CALLBACK __export
+config_vars_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+BOOL CALLBACK __export
+config_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+void
+init_screen(void)
+{
+ /*
+ * If we want to show it, turn it on. If we don't care, put it back
+ * to the way it was originally.
+ */
+ mswin_showcaret(F_ON(F_SHOW_CURSOR, ps_global));
+ mswin_trayicon(F_ON(F_ENABLE_TRAYICON, ps_global));
+ return; /* NO OP */
+}
+
+void
+end_screen(char *message, int exit_val)
+{
+ int footer_rows_was_one = 0;
+
+ if(panicking())
+ return;
+
+ if(FOOTER_ROWS(ps_global) == 1){
+ footer_rows_was_one++;
+ FOOTER_ROWS(ps_global) = 3;
+ mark_status_unknown();
+ }
+
+ flush_status_messages(exit_val ? 0 : 1);
+
+ blank_keymenu(_lines - 2, 0);
+
+ if(message){
+ StartInverse();
+ PutLine0(_lines - 2, 0, message);
+ }
+
+ EndInverse();
+
+ MoveCursor(_lines - 1, 0);
+
+ mswin_showcaret(F_ON(F_SHOW_CURSOR, ps_global));
+
+ if(footer_rows_was_one){
+ FOOTER_ROWS(ps_global) = 1;
+ mark_status_unknown();
+ }
+}
+
+/*----------------------------------------------------------------------
+ Initialize the screen for output, set terminal type, etc
+
+ Args: tt -- Pointer to variable to store the tty output structure.
+
+ Result: terminal size is discovered and set pine state
+ termcap entry is fetched and stored in local variables
+ make sure terminal has adequate capabilites
+ evaluate scrolling situation
+ returns status of indicating the state of the screen/termcap entry
+
+ Returns:
+ -1 indicating no terminal name associated with this shell,
+ -2..-n No termcap for this terminal type known
+ -3 Can't open termcap file
+ -4 Terminal not powerful enough - missing clear to eoln or screen
+ or cursor motion
+
+ ----*/
+int
+config_screen(struct ttyo **tt)
+{
+ struct ttyo *ttyo;
+
+ _line = 0; /* where are we right now?? */
+ _col = 0; /* assume zero, zero... */
+
+ mswin_getscreensize(&_lines, &_columns);
+ if (_lines > MAX_SCREEN_ROWS)
+ _lines = MAX_SCREEN_ROWS;
+ if (_columns > MAX_SCREEN_COLS)
+ _columns = MAX_SCREEN_COLS;
+
+ ttyo = (struct ttyo *)fs_get(sizeof(struct ttyo));
+ ttyo->screen_cols = _columns;
+ ttyo->screen_rows = _lines ;
+ ttyo->header_rows = 2;
+ ttyo->footer_rows = 3;
+
+ *tt = ttyo;
+
+ return(0);
+}
+
+/*----------------------------------------------------------------------
+ Get the current window size
+
+ Args: ttyo -- pointer to structure to store window size in
+
+ NOTE: we don't override the given values unless we know better
+ ----*/
+int
+get_windsize(struct ttyo *ttyo)
+{
+ char fontName[LF_FACESIZE+1];
+ char fontSize[12];
+ char fontStyle[64];
+ char fontCharSet[256];
+ char windowPosition[32], windowPositionReg[32];
+ char foreColor[64], backColor[64];
+ int newRows, newCols;
+ char cursorStyle[32];
+
+ cursorStyle[0] = '\0';
+
+ /* Get the new window parameters and update the 'pinerc' variables. */
+ mswin_getwindow(fontName, sizeof(fontName), fontSize, sizeof(fontSize),
+ fontStyle, sizeof(fontStyle),
+ windowPosition, sizeof(windowPosition),
+ foreColor, sizeof(foreColor),
+ backColor, sizeof(backColor),
+ cursorStyle, sizeof(cursorStyle),
+ fontCharSet, sizeof(fontCharSet));
+
+ if(!ps_global->VAR_FONT_NAME
+ || strucmp(ps_global->VAR_FONT_NAME, fontName))
+ set_variable(V_FONT_NAME, fontName, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ if(!ps_global->VAR_FONT_SIZE
+ || strucmp(ps_global->VAR_FONT_SIZE, fontSize))
+ set_variable(V_FONT_SIZE, fontSize, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ if(!ps_global->VAR_FONT_STYLE
+ || strucmp(ps_global->VAR_FONT_STYLE, fontStyle))
+ set_variable(V_FONT_STYLE, fontStyle, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ if(!ps_global->VAR_FONT_CHAR_SET
+ || strucmp(ps_global->VAR_FONT_CHAR_SET, fontCharSet))
+ set_variable(V_FONT_CHAR_SET, fontCharSet, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ if(strnicmp(windowPosition, "MIN0", 4) && !strchr(windowPosition, '!')){
+ if(F_ON(F_STORE_WINPOS_IN_CONFIG, ps_global)){
+ if(!ps_global->VAR_WINDOW_POSITION
+ || strucmp(ps_global->VAR_WINDOW_POSITION, windowPosition))
+ set_variable(V_WINDOW_POSITION, windowPosition, 1, 0,
+ ps_global->ew_for_except_vars);
+ }
+ else{
+ /*
+ * Get the window position stored in the registry.
+ *
+ * If current window position is not in the registry or is
+ * different from what is there, save it.
+ */
+ if((!mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, windowPositionReg,
+ sizeof(windowPositionReg)) ||
+ strucmp(windowPositionReg, windowPosition))
+ && (ps_global->update_registry != UREG_NEVER_SET))
+ mswin_reg(MSWR_OP_SET | MSWR_OP_FORCE, MSWR_PINE_POS, windowPosition,
+ (size_t)NULL);
+ }
+ }
+
+ mswin_getprintfont(fontName, sizeof(fontName),
+ fontSize, sizeof(fontSize),
+ fontStyle, sizeof(fontStyle),
+ fontCharSet, sizeof(fontCharSet));
+ if(!ps_global->VAR_PRINT_FONT_NAME
+ || strucmp(ps_global->VAR_PRINT_FONT_NAME, fontName))
+ set_variable(V_PRINT_FONT_NAME, fontName, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ if(!ps_global->VAR_PRINT_FONT_SIZE
+ || strucmp(ps_global->VAR_PRINT_FONT_SIZE, fontSize))
+ set_variable(V_PRINT_FONT_SIZE, fontSize, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ if(!ps_global->VAR_PRINT_FONT_STYLE
+ || strucmp(ps_global->VAR_PRINT_FONT_STYLE, fontStyle))
+ set_variable(V_PRINT_FONT_STYLE, fontStyle, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ if(!ps_global->VAR_PRINT_FONT_CHAR_SET
+ || strucmp(ps_global->VAR_PRINT_FONT_CHAR_SET, fontCharSet))
+ set_variable(V_PRINT_FONT_CHAR_SET, fontCharSet, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ if(!ps_global->VAR_NORM_FORE_COLOR
+ || strucmp(ps_global->VAR_NORM_FORE_COLOR, foreColor))
+ set_variable(V_NORM_FORE_COLOR, foreColor, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ if(!ps_global->VAR_NORM_BACK_COLOR
+ || strucmp(ps_global->VAR_NORM_BACK_COLOR, backColor))
+ set_variable(V_NORM_BACK_COLOR, backColor, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ if(cursorStyle[0] && !ps_global->VAR_CURSOR_STYLE
+ || strucmp(ps_global->VAR_CURSOR_STYLE, cursorStyle))
+ set_variable(V_CURSOR_STYLE, cursorStyle, 1, 0,
+ ps_global->ew_for_except_vars);
+
+ /* Get new window size. Compare to old. The window may have just
+ * moved, in which case we don't bother updating the size. */
+ mswin_getscreensize(&newRows, &newCols);
+ if (newRows == ttyo->screen_rows && newCols == ttyo->screen_cols)
+ return (NO_OP_COMMAND);
+
+ /* True resize. */
+ ttyo->screen_rows = newRows;
+ ttyo->screen_cols = newCols;
+
+ if (ttyo->screen_rows > MAX_SCREEN_ROWS)
+ ttyo->screen_rows = MAX_SCREEN_ROWS;
+ if (ttyo->screen_cols > MAX_SCREEN_COLS)
+ ttyo->screen_cols = MAX_SCREEN_COLS;
+
+ return(KEY_RESIZE);
+}
+
+/*----------------------------------------------------------------------
+ Move the cursor to the row and column number
+ Input: row number
+ column number
+
+ Result: Cursor moves
+ internal position updated
+ ----------------------------------------------------------------------*/
+void
+MoveCursor(int row, int col)
+{
+ /** move cursor to the specified row column on the screen.
+ 0,0 is the top left! **/
+
+ if(ps_global->in_init_seq)
+ return;
+
+ /*
+ * This little hack is here for screen readers, for example, a screen
+ * reader associated with a braille display. If we flash the cursor off
+ * and on in the same position, the reader will be drawn to it. Since we
+ * are calling MoveCursor every time through the message viewing loops we
+ * need to suppress the calls if they aren't really doing anything.
+ * However, mswin_move actually does more than just move the cursor.
+ * It also call FlushAccum(), which is necessary in some cases. For
+ * example, in optionally_enter the user is typing characters in and
+ * the FlushAccum() allows them to show up on the screen. The putblock
+ * call is a quick hack to get the Flush_Accum() call, which is all
+ * the putblock does when the arg is NULL.
+ */
+ if(row == _line && col == _col){
+ mswin_putblock(NULL, 0);
+ return;
+ }
+
+ mswin_move(row, col);
+ _line = row;
+ _col = col;
+}
+
+
+/*----------------------------------------------------------------------
+ Write a character to the screen, keeping track of cursor position
+
+ Input: charater to write
+
+ Result: character output
+ cursor position variables updated
+ ----------------------------------------------------------------------*/
+void
+Writewchar(UCS ucs)
+{
+ int width;
+
+ if(ps_global->in_init_seq)
+ return;
+
+ switch(ucs){
+ case LINE_FEED :
+ _line = min(_line+1,ps_global->ttyo->screen_rows);
+ _col =0;
+ mswin_move(_line, _col);
+ break;
+
+ case RETURN : /* move to column 0 */
+ _col = 0;
+ mswin_move(_line, _col);
+
+ case BACKSPACE : /* move back a space if not in column 0 */
+ if(_col > 0)
+ mswin_move(_line, --_col);
+
+ break;
+
+ case BELL : /* ring the bell but don't advance _col */
+ mswin_beep(); /* libpico call */
+ break;
+
+ case TAB: /* if a tab, output it */
+ do
+ mswin_putc(' ');
+ while(((++_col)&0x07) != 0);
+ break;
+
+ default:
+ /* pass_ctrl_chars is always 1 for Windows */
+ width = wcellwidth(ucs);
+ if(width < 0){
+ mswin_putc('?');
+ _col++;
+ }
+ else if(_col + width > ps_global->ttyo->screen_cols){
+ int i;
+
+ i = ps_global->ttyo->screen_cols - _col - 1;
+ while(i-- > 0)
+ mswin_putc(' ');
+
+ _col = ps_global->ttyo->screen_cols - 1;
+ mswin_move(_line, _col);
+ mswin_putc('>');
+ _col++;
+ }
+ else{
+ mswin_putc(ucs);
+ _col += width;
+ }
+ }
+
+ if(_col >= ps_global->ttyo->screen_cols){
+ _col = ps_global->ttyo->screen_cols;
+ mswin_move(_line, _col);
+ }
+
+ return;
+}
+
+
+/*----------------------------------------------------------------------
+ Printf style write directly to the terminal at current position
+
+ Input: printf style control string
+ number of printf style arguments
+ up to three printf style arguments
+
+ Result: Line written to the screen
+ ----------------------------------------------------------------------*/
+void
+Write_to_screen(char *string)
+{
+ if(ps_global->in_init_seq)
+ return;
+
+ mswin_puts (string);
+
+ /*
+ * mswin_puts does not keep track of where we are. Simple fix is to
+ * reset _line and _col to unknown so that the next MoveCursor will
+ * do a real move. We could check for a simple string and actually
+ * keep track. Is that useful? I don't think so.
+ *
+ * There are other places where we lose track, but by comparing with
+ * the termout.unx code where we also lose track it would seem we don't
+ * really need to keep track in those other cases.
+ */
+ _line = FARAWAY;
+ _col = FARAWAY;
+}
+
+void
+Write_to_screen_n(char *string, int n)
+{
+ if(ps_global->in_init_seq)
+ return;
+
+ mswin_puts_n (string, n);
+ _line = FARAWAY;
+ _col = FARAWAY;
+}
+
+
+/*----------------------------------------------------------------------
+ Clear the terminal screen
+ ----------------------------------------------------------------------*/
+void
+ClearScreen(void)
+{
+ _line = 0; /* clear leaves us at top... */
+ _col = 0;
+
+ if(ps_global->in_init_seq)
+ return;
+
+ mark_status_unknown();
+ mark_keymenu_dirty();
+ mark_titlebar_dirty();
+
+ mswin_move(0, 0);
+ mswin_eeop();
+}
+
+/*----------------------------------------------------------------------
+ Clear screen to end of line on current line
+ ----------------------------------------------------------------------*/
+void
+CleartoEOLN(void)
+{
+ mswin_eeol();
+}
+
+
+/*----------------------------------------------------------------------
+ function to output string such that it becomes icon text
+
+ Args: s -- string to write
+
+ Result: string indicated become our "icon" text
+ ----*/
+void
+icon_text(char *s, int type)
+{
+ if(type == IT_MCLOSED)
+ mswin_mclosedtext (s);
+ else /* IT_NEWMAIL */
+ mswin_newmailtext (s);
+}
+
+/* Scroll stuff */
+
+/*
+ * Set the current position of the scroll bar.
+ */
+void
+scroll_setpos(long newpos)
+{
+ mswin_setscrollpos (newpos);
+}
+
+/*
+ * Set the range of the scroll bar.
+ * zero disables the scroll bar.
+ */
+void
+scroll_setrange (long pagelen, long rangeend)
+{
+ if(rangeend < pagelen)
+ mswin_setscrollrange (0L, 0L);
+ else
+ mswin_setscrollrange (pagelen, rangeend + pagelen - 1L);
+}
+
+void
+EndScroll(void)
+{
+}
+
+int
+ScrollRegion(int lines)
+{
+ return(-1);
+}
+
+int
+BeginScroll(int top, int bottom)
+{
+ static int __t, __b;
+
+ __t = top;
+ __b = bottom;
+ return(-1);
+}
+
+
+/* Dialog stuff */
+#define WINDOW_USER_DATA GWL_USERDATA
+
+/*===========================================================================
+ *
+ * Dialog Data
+ *
+ * The following structures hold the state data for dialogs.
+ */
+typedef struct DLG_TYPEMAP {
+ int pineid;
+ int rsrcid;
+} DLG_TYPEMAP;
+
+typedef struct DLG_SORTDATA {
+ DLG_SORTPARAM *sortsel; /* parameter structure. */
+ int sortcount; /* Number of different sorts. */
+ DLG_TYPEMAP types[20]; /* Map pine sort types to ctrl ids. */
+} DLG_SORTDATA;
+
+typedef struct DLG_LOGINDATA {
+ NETMBX *mb;
+ LPTSTR user;
+ int userlen;
+ LPTSTR pwd;
+ int pwdlen;
+ int pwc; /* set if we're using passfiles and we don't know user yet */
+ int fixuser;
+ int prespass; /* if user wants to preserve the password */
+ int rv;
+} DLG_LOGINDATA;
+
+typedef struct DLG_CONFIGDATA {
+ char *confpath; /* UTF-8 path */
+ int confpathlen;
+ int setreg;
+ int nopinerc;
+ int rv;
+} DLG_CONFIGDATA;
+
+typedef struct installvars {
+ char *pname;
+ char *userid;
+ char *domain;
+ char *inboxpath;
+ char *smtpserver;
+ unsigned defmailclient:1;
+ unsigned defnewsclient:1;
+} INSTALLVARS_S;
+
+typedef struct DLG_CONGIGVARSDATA {
+ INSTALLVARS_S *ivars;
+ int rv;
+} DLG_CONFIGVARSDATA;
+
+typedef struct DLG_FLAGDATA {
+ struct flag_table *ftbl;
+ int flagcount;
+ HINSTANCE hInstance;
+ HWND hTextWnd;
+} DLG_FLAGDATA;
+
+int os_config_vars_dialog(INSTALLVARS_S *);
+static void GetBtnPos (HWND, HWND, RECT *);
+
+int
+init_install_get_vars(void)
+{
+ INSTALLVARS_S ivars;
+ struct pine *ps = ps_global;
+ char *p;
+
+ memset((void *)&ivars, 0, sizeof(INSTALLVARS_S));
+ if(ps->vars[V_PERSONAL_NAME].main_user_val.p)
+ ivars.pname = cpystr(ps->vars[V_PERSONAL_NAME].main_user_val.p);
+ if(ps->vars[V_USER_ID].main_user_val.p)
+ ivars.userid = cpystr(ps->vars[V_USER_ID].main_user_val.p);
+ if(ps->vars[V_USER_DOMAIN].main_user_val.p)
+ ivars.domain = cpystr(ps->vars[V_USER_DOMAIN].main_user_val.p);
+ if(ps->vars[V_INBOX_PATH].main_user_val.p)
+ ivars.inboxpath = cpystr(ps->vars[V_INBOX_PATH].main_user_val.p);
+ else if(ps->prc && ps->prc->name && (*ps->prc->name == '{')
+ && (p = strindex(ps->prc->name, '}'))){
+ ivars.inboxpath = cpystr(ps->prc->name);
+ if(p = strindex(ivars.inboxpath, '}'))
+ *(p+1) = '\0';
+ }
+ if(ps->vars[V_SMTP_SERVER].main_user_val.l
+ && *ps->vars[V_SMTP_SERVER].main_user_val.l)
+ ivars.smtpserver = cpystr(ps->vars[V_SMTP_SERVER].main_user_val.l[0]);
+ ivars.defmailclient = mswin_is_def_client(MSWR_SDC_MAIL);
+ ivars.defnewsclient = mswin_is_def_client(MSWR_SDC_NEWS);
+
+ if(os_config_vars_dialog(&ivars) == 0){
+ set_variable(V_PERSONAL_NAME, ivars.pname, 0, 0, Main);
+ set_variable(V_USER_ID, ivars.userid, 0, 0, Main);
+ set_variable(V_USER_DOMAIN, ivars.domain, 0, 0, Main);
+ set_variable(V_INBOX_PATH, ivars.inboxpath, 0, 0, Main);
+ if(ivars.smtpserver){
+ if(ps->vars[V_SMTP_SERVER].main_user_val.l){
+ fs_give((void **)&ps->vars[V_SMTP_SERVER].main_user_val.l[0]);
+ ps->vars[V_SMTP_SERVER].main_user_val.l[0]
+ = cpystr(ivars.smtpserver);
+ set_current_val(&ps->vars[V_SMTP_SERVER], TRUE, FALSE);
+ }
+ else {
+ char *tstrlist[2];
+
+ tstrlist[0] = ivars.smtpserver;
+ tstrlist[1] = NULL;
+ set_variable_list(V_SMTP_SERVER, tstrlist, 0, Main);
+ }
+ }
+ write_pinerc(ps_global, Main, WRP_NONE);
+ if(ivars.defmailclient)
+ mswin_set_def_client(MSWR_SDC_MAIL);
+ if(ivars.defnewsclient)
+ mswin_set_def_client(MSWR_SDC_NEWS);
+
+ /* Tell Windows that stuff has changed */
+ if(ivars.defmailclient || ivars.defnewsclient)
+ SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE,
+ (WPARAM)NULL, (LPARAM)NULL,
+ SMTO_NORMAL, 1000, NULL);
+ }
+
+ if(ivars.pname)
+ fs_give((void **)&ivars.pname);
+ if(ivars.userid)
+ fs_give((void **)&ivars.userid);
+ if(ivars.domain)
+ fs_give((void **)&ivars.domain);
+ if(ivars.inboxpath)
+ fs_give((void **)&ivars.inboxpath);
+ if(ivars.smtpserver)
+ fs_give((void **)&ivars.smtpserver);
+ return 0;
+}
+
+/*
+ * Show args dialog
+ */
+int
+os_argsdialog (char **arg_text)
+{
+ DLGPROC dlgprc;
+ HINSTANCE hInst;
+ HWND hWnd;
+
+ hInst = (HINSTANCE) mswin_gethinstance ();
+ hWnd = (HWND) mswin_gethwnd ();
+
+ mswin_killsplash();
+
+ dlgprc = args_dialog_proc;
+
+ DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_ARGLIST), hWnd,
+ dlgprc, (LPARAM) arg_text);
+
+ return(1);
+}
+
+/*
+ * Prompt for username and password
+ */
+int
+os_login_dialog (NETMBX *mb, char *user_utf8, int userlen,
+ char *pwd_utf8, int pwdlen, int pwc, int fixuser, int *prespass)
+{
+ DLGPROC dlgprc;
+ HINSTANCE hInst;
+ HWND hWnd;
+ DLG_LOGINDATA dlgpw;
+ LPTSTR user_lptstr, pwd_lptstr;
+ char *tuser_utf8, *tpwd_utf8;
+
+ mswin_killsplash();
+ hInst = (HINSTANCE) mswin_gethinstance ();
+ hWnd = (HWND) mswin_gethwnd ();
+
+ dlgpw.mb = mb;
+
+ dlgpw.user = (LPTSTR)fs_get(userlen*sizeof(TCHAR));
+ user_lptstr = utf8_to_lptstr(user_utf8);
+ _tcsncpy(dlgpw.user, user_lptstr, userlen - 1);
+ dlgpw.user[userlen - 1] = '\0';
+ fs_give((void **) &user_lptstr);
+ dlgpw.userlen = userlen;
+
+ dlgpw.pwd = (LPTSTR)fs_get(pwdlen*sizeof(TCHAR));
+ pwd_lptstr = utf8_to_lptstr(pwd_utf8);
+ _tcsncpy(dlgpw.pwd, pwd_lptstr, pwdlen - 1);
+ dlgpw.pwd[pwdlen - 1] = '\0';
+ fs_give((void **) &pwd_lptstr);
+ dlgpw.pwdlen = pwdlen;
+
+ dlgpw.fixuser = fixuser;
+ dlgpw.pwc = pwc;
+ dlgpw.rv = 0;
+
+ dlgprc = login_dialog_proc;
+
+ DialogBoxParam (hInst, MAKEINTRESOURCE (ps_global->install_flag
+ ? IDD_LOGINDLG2 : IDD_LOGINDLG),
+ NULL, dlgprc, (LPARAM)&dlgpw);
+
+ if(dlgpw.rv == 0){
+ tuser_utf8 = lptstr_to_utf8(dlgpw.user);
+ if(tuser_utf8){
+ strncpy(user_utf8, tuser_utf8, userlen - 1);
+ user_utf8[userlen - 1] = '\0';
+ fs_give((void **) &tuser_utf8);
+ }
+
+ tpwd_utf8 = lptstr_to_utf8(dlgpw.pwd);
+ if(tpwd_utf8){
+ strncpy(pwd_utf8, tpwd_utf8, pwdlen - 1);
+ pwd_utf8[pwdlen - 1] = '\0';
+ fs_give((void **) &tpwd_utf8);
+ }
+ if(prespass)
+ (*prespass) = dlgpw.prespass;
+ }
+
+ return(dlgpw.rv);
+}
+
+/*
+ * Select message flags.
+ */
+int
+os_flagmsgdialog (struct flag_table *ftbl)
+{
+ DLGPROC dlgprc;
+ HINSTANCE hInst;
+ HWND hWnd;
+ DLG_FLAGDATA dlgflag;
+ int rval;
+
+ hInst = (HINSTANCE) mswin_gethinstance ();
+ hWnd = (HWND) mswin_gethwnd ();
+
+ dlgflag.ftbl = ftbl;
+ dlgflag.hInstance = hInst;
+ dlgflag.hTextWnd = hWnd;
+
+ dlgprc = flag_dialog_proc;
+
+ rval = DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_SELECTFLAG), hWnd,
+ dlgprc, (LPARAM)&dlgflag);
+
+ return (rval);
+}
+
+/*
+ * Select a sort type.
+ */
+
+int
+os_sortdialog (DLG_SORTPARAM *sortsel)
+{
+ DLGPROC dlgprc;
+ HINSTANCE hInst;
+ HWND hWnd;
+ int i;
+ DLG_SORTDATA dlgsort;
+
+ hInst = (HINSTANCE) mswin_gethinstance ();
+ hWnd = (HWND) mswin_gethwnd ();
+
+
+ /* Build a map of pine sort types to the resource types. */
+ i = 0;
+ dlgsort.types[i].pineid = SortArrival;
+ dlgsort.types[i++].rsrcid = IDC_SORTARRIVAL;
+ dlgsort.types[i].pineid = SortDate;
+ dlgsort.types[i++].rsrcid = IDC_SORTDATE;
+ dlgsort.types[i].pineid = SortFrom;
+ dlgsort.types[i++].rsrcid = IDC_SORTFROM;
+ dlgsort.types[i].pineid = SortSubject;
+ dlgsort.types[i++].rsrcid = IDC_SORTSUBJECT;
+ dlgsort.types[i].pineid = SortSubject2;
+ dlgsort.types[i++].rsrcid = IDC_SORTORDERSUB;
+ dlgsort.types[i].pineid = SortTo;
+ dlgsort.types[i++].rsrcid = IDC_SORTTO;
+ dlgsort.types[i].pineid = SortCc;
+ dlgsort.types[i++].rsrcid = IDC_SORTCC;
+ dlgsort.types[i].pineid = SortSize;
+ dlgsort.types[i++].rsrcid = IDC_SORTSIZE;
+ dlgsort.types[i].pineid = SortThread;
+ dlgsort.types[i++].rsrcid = IDC_SORTTHREAD;
+ dlgsort.types[i].pineid = SortScore;
+ dlgsort.types[i++].rsrcid = IDC_SORTSCORE;
+ dlgsort.sortcount = i;
+ dlgsort.sortsel = sortsel;
+
+ dlgprc = sort_dialog_proc;
+
+ DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_SELECTSORT), hWnd,
+ dlgprc, (LPARAM)&dlgsort);
+
+ return(1);
+}
+
+
+/*
+ * Dialog proc to handle index sort selection.
+ *
+ * Configures the dialog box on init and retrieves the settings on exit.
+ */
+BOOL CALLBACK __export
+args_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL ret = FALSE;
+ long i, j, block_size;
+ char **args_text;
+ LPTSTR args_text_lptstr, args_block_lptstr;
+
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+
+ args_text = (char **)lParam;
+
+ /*
+ * First convert char *'s over to one big block of
+ * Unicode
+ */
+ i = 0;
+ while(args_text && *args_text){
+ i += strlen(*args_text++);
+ i += 2;
+ }
+ block_size = i;
+
+ args_block_lptstr = (LPTSTR)fs_get((block_size+1)*sizeof(TCHAR));
+
+ args_text = (char **)lParam;
+ i = 0;
+ j = 0;
+ while(args_text && *args_text){
+ args_text_lptstr = utf8_to_lptstr(*args_text++);
+ while(args_text_lptstr[i] && j < block_size){
+ args_block_lptstr[j++] = args_text_lptstr[i++];
+ }
+ args_block_lptstr[j++] = '\r';
+ args_block_lptstr[j++] = '\n';
+ fs_give((void **) &args_text_lptstr);
+ i = 0;
+ }
+ args_block_lptstr[j] = '\0';
+
+ /* and replace everything selected with args_text */
+ SendDlgItemMessage(hDlg, IDC_ARGTEXT, WM_SETTEXT, (WPARAM) 0,
+ (LPARAM) args_block_lptstr);
+ fs_give((void **)&args_block_lptstr);
+
+ return (1);
+
+ case WM_CLOSE :
+ ret = TRUE;
+ EndDialog (hDlg, TRUE);
+ break;
+
+
+ case WM_COMMAND:
+ switch (wParam) {
+ case IDOK:
+ ret = TRUE;
+ EndDialog (hDlg, TRUE);
+ break;
+ }
+ break;
+
+
+ }
+ return (ret);
+}
+
+/*
+ * Dialog proc to handle login
+ *
+ * Configures the dialog box on init and retrieves the settings on exit.
+ */
+BOOL CALLBACK __export
+login_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ DLG_LOGINDATA *dlglogin;
+ BOOL ret = FALSE;
+ TCHAR tcbuf[1024];
+ NETMBX *mb;
+ LPTSTR user, pwd;
+ LPTSTR host_lptstr;
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+
+ dlglogin = (DLG_LOGINDATA *)lParam;
+ mb = dlglogin->mb;
+ user = dlglogin->user;
+ pwd = dlglogin->pwd;
+ SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlglogin);
+
+ host_lptstr = utf8_to_lptstr(mb->host);
+ _sntprintf(tcbuf, sizeof(tcbuf), TEXT("Host: %.100s%s"), host_lptstr,
+ !mb->sslflag && !mb->tlsflag ? TEXT(" (INSECURE)") : TEXT(""));
+ fs_give((void **) &host_lptstr);
+
+ if(mb->sslflag || mb->tlsflag)
+ SetWindowText(hDlg, TEXT("Alpine Login +"));
+ else
+ SetWindowText(hDlg, TEXT("Alpine Insecure Login"));
+
+ if(dlglogin->pwc){
+ EnableWindow(GetDlgItem(hDlg, IDC_RPASSWORD),0);
+ EnableWindow(GetDlgItem(hDlg, IDC_RPWTEXT),0);
+ EnableWindow(GetDlgItem(hDlg, IDC_PRESPASS),0);
+ }
+ if(mb->user && *mb->user){
+ LPTSTR user_lptstr;
+
+ user_lptstr = utf8_to_lptstr(mb->user);
+ SetDlgItemText(hDlg, IDC_RLOGINE, user_lptstr);
+ if((mb->user && *mb->user) || dlglogin->fixuser)
+ EnableWindow(GetDlgItem(hDlg, IDC_RLOGINE), 0);
+ fs_give((void **) &user_lptstr);
+ }
+ else if(user){
+ SetDlgItemText(hDlg, IDC_RLOGINE, user);
+ if(dlglogin->fixuser)
+ EnableWindow(GetDlgItem(hDlg, IDC_RLOGINE), 0);
+ }
+ SetDlgItemText(hDlg, IDC_PROMPT, tcbuf);
+ return (1);
+
+
+ case WM_COMMAND:
+ dlglogin = (DLG_LOGINDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
+ switch (wParam) {
+ case IDOK:
+ /* Retrieve the new username/passwd. */
+ user = dlglogin->user;
+ pwd = dlglogin->pwd;
+ GetDlgItemText(hDlg, IDC_RLOGINE, user, dlglogin->userlen - 1);
+ GetDlgItemText(hDlg, IDC_RPASSWORD, pwd, dlglogin->pwdlen - 1);
+ user[dlglogin->userlen - 1] = '\0';
+ pwd[dlglogin->pwdlen - 1] = '\0';
+ dlglogin->prespass = (IsDlgButtonChecked(hDlg, IDC_PRESPASS) == BST_CHECKED);
+
+ EndDialog (hDlg, LOWORD(wParam));
+ dlglogin->rv = 0;
+ ret = TRUE;
+ break;
+
+ case IDCANCEL:
+ dlglogin->rv = 1;
+ ret = TRUE;
+ EndDialog (hDlg, LOWORD(wParam));
+ break;
+ }
+ break;
+ }
+ return (ret);
+}
+
+/*
+ * Dialog proc to handle flag selection.
+ *
+ * Configures the dialog box on init, adding buttons as needed for
+ * an unknown number of flags.
+ * Retrieves the settings on exit.
+ */
+BOOL CALLBACK __export
+flag_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ DLG_FLAGDATA *dlgflag;
+ BOOL ret = FALSE;
+ int i;
+ struct flag_table *fp;
+ HWND hRB[2], hBtn;
+ RECT rb[2];
+ UINT bheight, bwidth, bvertSpace;
+ UINT btnOKHeight;
+ int base, line;
+ int bstate;
+ HFONT btnFont;
+
+
+
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ dlgflag = (DLG_FLAGDATA *)lParam;
+ SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgflag);
+
+ /* Count buttons */
+ dlgflag->flagcount = 0;
+ for (fp = dlgflag->ftbl; fp && fp->name; ++fp)
+ ++dlgflag->flagcount;
+
+ /* Get the positions of the current buttons. */
+ for (i = 0; i < 2; ++i) {
+ hRB[i] = GetDlgItem (hDlg, IDC_FLAGCOL1 + i);
+ GetBtnPos (hDlg, hRB[i], &rb[i]);
+ }
+ bheight = rb[0].bottom - rb[0].top;
+ bwidth = rb[0].right - rb[0].left;
+ bvertSpace = bheight + 5;
+ btnFont = (HFONT) SendMessage (hRB[0], WM_GETFONT, 0, 0);
+
+ for (i = 0; i < dlgflag->flagcount; ++i) {
+ LPTSTR fp_name_lptstr;
+
+ fp = &dlgflag->ftbl[i];
+
+ fp_name_lptstr = utf8_to_lptstr(fp->name);
+ if (i < 2) {
+ hBtn = hRB[i];
+ SetWindowText (hBtn, fp_name_lptstr);
+ }
+ else {
+ base = i % 2;
+ line = i / 2;
+ hBtn = CreateWindow (TEXT("BUTTON"), fp_name_lptstr,
+ WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
+ rb[base].left, rb[base].top + bvertSpace * line,
+ bwidth, bheight,
+ hDlg, (HMENU)NULL, dlgflag->hInstance, NULL);
+ SetWindowLong (hBtn, GWL_ID, IDC_FLAGCOL1 + i);
+ SendMessage (hBtn, WM_SETFONT, (WPARAM)btnFont,
+ MAKELPARAM (0, 0));
+ }
+
+ fs_give((void **) &fp_name_lptstr);
+ if (fp->ukn)
+ SendMessage (hBtn, BM_SETSTYLE,
+ (WPARAM)(BS_CHECKBOX | BS_AUTO3STATE), 0);
+ SendMessage (hBtn, BM_SETCHECK,
+ (WPARAM) fp->set == CMD_FLAG_UNKN ? 2 : fp->set ? 1 : 0,
+ 0);
+ ShowWindow (hBtn, SW_SHOW);
+ EnableWindow (hBtn, TRUE);
+ }
+
+ /* Position the OK and Cancel buttons. */
+ line = (dlgflag->flagcount + 1) / 2;
+ for (i = 0; i < 2; ++i) {
+ hRB[1] = GetDlgItem (hDlg, i == 0 ? IDOK : IDCANCEL);
+ GetBtnPos (hDlg, hRB[1], &rb[1]);
+ MoveWindow (hRB[1], rb[1].left, rb[0].top + bvertSpace * line,
+ rb[1].right - rb[1].left, rb[1].bottom - rb[1].top,
+ FALSE);
+ btnOKHeight = rb[1].bottom - rb[1].top;
+ }
+
+
+ /* Resize whole dialog window. */
+ GetWindowRect (hDlg, &rb[1]);
+ rb[1].right -= rb[1].left;
+ rb[1].bottom = rb[0].top + bvertSpace * line + btnOKHeight + 10 +
+ GetSystemMetrics (SM_CYCAPTION);
+ MoveWindow (hDlg, rb[1].left, rb[1].top, rb[1].right,
+ rb[1].bottom, TRUE);
+ return (1);
+
+
+ case WM_COMMAND:
+ dlgflag = (DLG_FLAGDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
+ switch (wParam) {
+
+ case IDOK:
+ /* Retrieve the button states. */
+ for (i = 0; i < dlgflag->flagcount; ++i) {
+ fp = &dlgflag->ftbl[i];
+ bstate = SendMessage (GetDlgItem (hDlg, IDC_FLAGCOL1 + i),
+ BM_GETCHECK, 0, 0);
+ switch (bstate) {
+ case 2: fp->set = CMD_FLAG_UNKN; break;
+ case 1: fp->set = CMD_FLAG_SET; break;
+ case 0: fp->set = CMD_FLAG_CLEAR; break;
+ }
+ }
+ EndDialog (hDlg, TRUE);
+ ret = TRUE;
+ break;
+
+ case IDCANCEL:
+ EndDialog (hDlg, FALSE);
+ ret = TRUE;
+ break;
+ }
+ break;
+
+
+ }
+ return (ret);
+}
+
+/*
+ * Dialog proc to handle index sort selection.
+ *
+ * Configures the dialog box on init and retrieves the settings on exit.
+ */
+BOOL CALLBACK __export
+sort_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ DLG_SORTDATA *dlgsort;
+ BOOL ret = FALSE;
+ int cursort;
+ int i;
+
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ dlgsort = (DLG_SORTDATA *)lParam;
+ SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgsort);
+
+ /* Set the reversed button state. */
+ CheckDlgButton (hDlg, IDC_SORTREVERSE, dlgsort->sortsel->reverse);
+
+ /* Set the current sort type radio button.*/
+ cursort = IDC_SORTARRIVAL;
+ for (i = 0; i < dlgsort->sortcount; ++i) {
+ if (dlgsort->types[i].pineid == dlgsort->sortsel->cursort) {
+ cursort = dlgsort->types[i].rsrcid;
+ break;
+ }
+ }
+ CheckRadioButton (hDlg, IDC_SORTFIRSTBUTTON, IDC_SORTLASTBUTTON,
+ cursort);
+
+ EnableWindow (GetDlgItem (hDlg, IDC_GETHELP),
+ (dlgsort->sortsel->helptext != NULL));
+ return (1);
+
+
+ case WM_COMMAND:
+ dlgsort = (DLG_SORTDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
+ switch (wParam) {
+ case IDC_GETHELP:
+ if (dlgsort->sortsel->helptext)
+ mswin_showhelpmsg ((WINHAND)hDlg, dlgsort->sortsel->helptext);
+ ret = TRUE;
+ break;
+
+ case IDOK:
+ dlgsort->sortsel->rval = 1;
+
+ /* Retrieve the reverse sort state. */
+ dlgsort->sortsel->reverse = (IsDlgButtonChecked (hDlg, IDC_SORTREVERSE) == 1);
+
+ /* Retrieve the new sort type. */
+ for (i = 0; i < dlgsort->sortcount; ++i) {
+ if (IsDlgButtonChecked (hDlg, dlgsort->types[i].rsrcid)) {
+ dlgsort->sortsel->cursort = dlgsort->types[i].pineid;
+ break;
+ }
+ }
+ EndDialog (hDlg, dlgsort->sortsel->rval);
+ ret = TRUE;
+ break;
+
+ case IDCANCEL:
+ dlgsort->sortsel->rval = 0;
+ ret = TRUE;
+ EndDialog (hDlg, dlgsort->sortsel->rval);
+ break;
+ }
+ break;
+
+
+ }
+ return (ret);
+}
+
+int
+os_config_vars_dialog (INSTALLVARS_S *ivars)
+{
+ DLGPROC dlgprc;
+ HINSTANCE hInst;
+ HWND hWnd;
+ DLG_CONFIGVARSDATA dlgcv;
+
+ mswin_killsplash();
+ hInst = (HINSTANCE) mswin_gethinstance ();
+ hWnd = (HWND) mswin_gethwnd ();
+
+ dlgcv.ivars = ivars;
+ dlgcv.rv = 0;
+
+ dlgprc = config_vars_dialog_proc;
+
+ DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_CFVARSDLG), NULL,
+ dlgprc, (LPARAM)&dlgcv);
+
+ return(dlgcv.rv);
+}
+
+/*
+ * Dialog proc to handle login
+ *
+ * Configures the dialog box on init and retrieves the settings on exit.
+ */
+BOOL CALLBACK __export
+config_vars_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ DLG_CONFIGVARSDATA *dlgcv;
+ BOOL ret = FALSE;
+ int usepop = 0;
+ char buf[2*MAXPATH+1], *p;
+ int buflen = 2*MAXPATH;
+#define TCBUFLEN (2*MAXPATH)
+ TCHAR tcbuf[TCBUFLEN+1];
+ LPTSTR tmp_lptstr;
+ char *u;
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ dlgcv = (DLG_CONFIGVARSDATA *)lParam;
+ SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgcv);
+ if(dlgcv->ivars->pname){
+ tmp_lptstr = utf8_to_lptstr(dlgcv->ivars->pname);
+ if(tmp_lptstr){
+ SetDlgItemText(hDlg, IDC_CFV_PNAME, tmp_lptstr);
+ fs_give((void **) &tmp_lptstr);
+ }
+ }
+
+ if(dlgcv->ivars->userid && dlgcv->ivars->domain){
+ snprintf(buf, sizeof(buf), "%.*s@%.*s", MAXPATH, dlgcv->ivars->userid,
+ MAXPATH, dlgcv->ivars->domain);
+ buf[buflen-1] = '\0';
+ tmp_lptstr = utf8_to_lptstr(buf);
+ if(tmp_lptstr){
+ SetDlgItemText(hDlg, IDC_CFV_EMAILADR, tmp_lptstr);
+ fs_give((void **) &tmp_lptstr);
+ }
+ }
+
+ if(dlgcv->ivars->inboxpath){
+ char *mbx;
+
+ mbx = dlgcv->ivars->inboxpath;
+ if(*mbx == '{' && (p = strindex(mbx, '}'))
+ && ((*(p+1) == '\0') || !strucmp(p+1, "inbox"))){
+ char srvbuf[MAXPATH+1], tuser[MAXPATH+1];
+ int i, j, k;
+
+ srvbuf[0] = '\0';
+ tuser[0] = '\0';
+ strncpy(buf, mbx+1, min(buflen, (int)(p - (mbx+1))));
+ buf[min(buflen-1, (int)(p - (mbx+1)))] = '\0';
+ for(i = 0, j = 0; buf[i] && j < MAXPATH; i++){
+ if(buf[i] == '/'){
+ if(!struncmp("/user=", buf+i, 6)){
+ i += 6;
+ for(k = 0; k < MAXPATH && buf[i]
+ && buf[i] != '/'; i++)
+ tuser[k++] = buf[i];
+ tuser[k] = '\0';
+ i--;
+ }
+ else if(!struncmp("/pop3", buf+i, 5)
+ && (!*(buf+5) || (*(buf+5) == '/'))){
+ usepop = 1;
+ i += 4;
+ }
+ else
+ srvbuf[j++] = buf[i];
+ }
+ else
+ srvbuf[j++] = buf[i];
+ }
+ srvbuf[j] = '\0';
+ if(*srvbuf){
+ tmp_lptstr = utf8_to_lptstr(srvbuf);
+ if(tmp_lptstr){
+ SetDlgItemText(hDlg, IDC_CFV_MSERVER, tmp_lptstr);
+ fs_give((void **) &tmp_lptstr);
+ }
+ }
+
+ if(*tuser){
+ tmp_lptstr = utf8_to_lptstr(tuser);
+ if(tmp_lptstr){
+ SetDlgItemText(hDlg, IDC_CFV_LOGIN, tmp_lptstr);
+ fs_give((void **) &tmp_lptstr);
+ }
+ }
+ }
+ else {
+ tmp_lptstr = utf8_to_lptstr(mbx);
+ if(tmp_lptstr){
+ SetDlgItemText(hDlg, IDC_CFV_MSERVER, tmp_lptstr);
+ fs_give((void **) &tmp_lptstr);
+ }
+
+ if(*mbx != '{' && *mbx != '#')
+ EnableWindow(GetDlgItem(hDlg, IDC_CFV_MSERVER), 0);
+ }
+ }
+ CheckRadioButton (hDlg, IDC_CFV_IMAP, IDC_CFV_POP3,
+ usepop ? IDC_CFV_POP3 : IDC_CFV_IMAP);
+ if(dlgcv->ivars->smtpserver){
+ tmp_lptstr = utf8_to_lptstr(dlgcv->ivars->smtpserver);
+ if(tmp_lptstr){
+ SetDlgItemText(hDlg, IDC_CFV_SMTPSERVER, tmp_lptstr);
+ fs_give((void **) &tmp_lptstr);
+ }
+ }
+
+ if(dlgcv->ivars->defmailclient)
+ CheckDlgButton(hDlg, IDC_CFV_DEFMAILER, BST_CHECKED);
+ if(dlgcv->ivars->defnewsclient)
+ CheckDlgButton(hDlg, IDC_CFV_DEFNEWSRDR, BST_CHECKED);
+
+ return (1);
+ break;
+
+ case WM_COMMAND:
+ dlgcv = (DLG_CONFIGVARSDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
+ switch (wParam) {
+ case IDOK:
+ /* personal name */
+ GetDlgItemText(hDlg, IDC_CFV_PNAME, tcbuf, TCBUFLEN);
+ tcbuf[TCBUFLEN] = '\0';
+ u = lptstr_to_utf8(tcbuf);
+ if(u){
+ removing_leading_and_trailing_white_space(u);
+ if(dlgcv->ivars->pname)
+ fs_give((void **)&dlgcv->ivars->pname);
+
+ if(*u){
+ dlgcv->ivars->pname = u;
+ u = NULL;
+ }
+
+ if(u)
+ fs_give((void **) &u);
+ }
+
+ /* user-id and domain */
+ GetDlgItemText(hDlg, IDC_CFV_EMAILADR, tcbuf, TCBUFLEN);
+ tcbuf[TCBUFLEN] = '\0';
+ u = lptstr_to_utf8(tcbuf);
+ if(u){
+ removing_leading_and_trailing_white_space(u);
+ if(p = strindex(u, '@')){
+ *(p++) = '\0';
+ if(dlgcv->ivars->userid)
+ fs_give((void **)&dlgcv->ivars->userid);
+
+ if(dlgcv->ivars->domain)
+ fs_give((void **)&dlgcv->ivars->domain);
+
+ if(*u){
+ dlgcv->ivars->userid = u;
+ u = NULL;
+ }
+
+ if(*p)
+ dlgcv->ivars->domain = cpystr(p);
+ }
+ else{
+ MessageBox(hDlg, TEXT("Invalid email address. Should be username@domain"),
+ TEXT("Alpine"), MB_ICONWARNING | MB_OK);
+ return(TRUE);
+ }
+
+ if(u)
+ fs_give((void **) &u);
+ }
+
+ /* inbox-path */
+ GetDlgItemText(hDlg, IDC_CFV_MSERVER, tcbuf, TCBUFLEN);
+ tcbuf[TCBUFLEN] = '\0';
+ u = lptstr_to_utf8(tcbuf);
+ if(u){
+ removing_leading_and_trailing_white_space(u);
+ if(*u == '{' || *u == '#'
+ || !IsWindowEnabled(GetDlgItem(hDlg, IDC_CFV_MSERVER))){
+ if(dlgcv->ivars->inboxpath)
+ fs_give((void **)&dlgcv->ivars->inboxpath);
+
+ dlgcv->ivars->inboxpath = u;
+ u = NULL;
+ }
+ else if(*u){
+ char tsrvr[4*MAXPATH+1];
+ int tsrvrlen = 4*MAXPATH;
+
+ if(dlgcv->ivars->inboxpath)
+ fs_give((void **)&dlgcv->ivars->inboxpath);
+
+ snprintf(tsrvr, sizeof(tsrvr), "{%s%s", u,
+ IsDlgButtonChecked(hDlg, IDC_CFV_POP3)
+ == BST_CHECKED ? "/pop3" : "");
+
+ if(u)
+ fs_give((void **) &u);
+
+ GetDlgItemText(hDlg, IDC_CFV_LOGIN, tcbuf, TCBUFLEN);
+ tcbuf[TCBUFLEN] = '\0';
+ u = lptstr_to_utf8(tcbuf);
+ if(u){
+ removing_leading_and_trailing_white_space(u);
+ if(*u){
+ strncat(tsrvr, "/user=", sizeof(tsrvr)-strlen(tsrvr)-1);
+ strncat(tsrvr, u, sizeof(tsrvr)-strlen(tsrvr)-1);
+ }
+
+ strncat(tsrvr, "}inbox", sizeof(tsrvr)-strlen(tsrvr)-1);
+ tsrvr[sizeof(tsrvr)-1] = '\0';
+ dlgcv->ivars->inboxpath = cpystr(tsrvr);
+ }
+ }
+
+ if(u)
+ fs_give((void **) &u);
+ }
+
+ /* smtp-server */
+ GetDlgItemText(hDlg, IDC_CFV_SMTPSERVER, tcbuf, TCBUFLEN);
+ tcbuf[TCBUFLEN] = '\0';
+ u = lptstr_to_utf8(tcbuf);
+ if(u){
+ removing_leading_and_trailing_white_space(u);
+ if(dlgcv->ivars->smtpserver)
+ fs_give((void **)&dlgcv->ivars->smtpserver);
+
+ if(*u){
+ dlgcv->ivars->smtpserver = u;
+ u = NULL;
+ }
+
+ if(u)
+ fs_give((void **) &u);
+ }
+
+ dlgcv->ivars->defmailclient =
+ (IsDlgButtonChecked(hDlg, IDC_CFV_DEFMAILER)
+ == BST_CHECKED);
+ dlgcv->ivars->defnewsclient =
+ (IsDlgButtonChecked(hDlg, IDC_CFV_DEFNEWSRDR)
+ == BST_CHECKED);
+
+ EndDialog (hDlg, LOWORD(wParam));
+ dlgcv->rv = 0;
+ ret = TRUE;
+ break;
+
+ case IDCANCEL:
+ dlgcv->rv = 1;
+ ret = TRUE;
+ EndDialog (hDlg, LOWORD(wParam));
+ break;
+ }
+ break;
+
+
+ }
+ return (ret);
+}
+
+/*
+ * Prompt for config location
+ */
+
+int
+os_config_dialog (char *utf8_buf, int utf8_buflen,
+ int *regset, int nopinerc)
+{
+ DLGPROC dlgprc;
+ HINSTANCE hInst;
+ HWND hWnd;
+ DLG_CONFIGDATA dlgcfg;
+
+ mswin_killsplash();
+ hInst = (HINSTANCE) mswin_gethinstance ();
+ hWnd = (HWND) mswin_gethwnd ();
+
+ dlgcfg.confpath = utf8_buf;
+ dlgcfg.confpathlen = utf8_buflen;
+ dlgcfg.setreg = 0;
+ dlgcfg.nopinerc = nopinerc;
+ dlgcfg.rv = 0;
+
+ dlgprc = config_dialog_proc;
+
+ DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_CONFIGDLG), NULL,
+ dlgprc, (LPARAM)&dlgcfg);
+
+ *regset = dlgcfg.setreg;
+ return(dlgcfg.rv);
+}
+
+
+/*
+ * Dialog proc to handle login
+ *
+ * Configures the dialog box on init and retrieves the settings on exit.
+ */
+BOOL CALLBACK __export
+config_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ DLG_CONFIGDATA *dlgcfg;
+ BOOL ret = FALSE;
+ int checked, def_rem_fldr = 1, def_diff_fldr = 0;
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+
+ dlgcfg = (DLG_CONFIGDATA *)lParam;
+ SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgcfg);
+ if(ps_global->install_flag)
+ SetDlgItemText(hDlg, IDC_CONFTEXT, TEXT("Please specify where Alpine should create (or look for) your personal configuration file."));
+ SetDlgItemText(hDlg, IDC_CONFEFLDRNAME, TEXT("remote_pinerc"));
+ if(*dlgcfg->confpath){
+ if(dlgcfg->confpath[0] == '{'){
+ LPTSTR tfldr, p, tfldr2, p2, user;
+
+ tfldr = utf8_to_lptstr((LPSTR)(dlgcfg->confpath+1));
+ if(p = _tcschr(tfldr, '}')){
+ *p++ = '\0';
+ if(_tcscmp(TEXT("remote_pinerc"), p)){
+ SetDlgItemText(hDlg, IDC_CONFEFLDRNAME, p);
+ def_diff_fldr = 1;
+ }
+
+ tfldr2 = _tcsdup(tfldr);
+ for(p = tfldr, p2 = tfldr2; *p; p++)
+ if(*p == '/' && !_tcsnicmp(p, TEXT("/user="), 6)){
+ p += 6;
+ for(user = p; *p && *p != '/'; p++);
+ if(*p){
+ *p2++ = *p;
+ *p = '\0';
+ }
+ else
+ p--;
+ SetDlgItemText(hDlg, IDC_CONFEUSERNAME, user);
+ }
+ else
+ *p2++ = *p;
+ *p2 = '\0';
+ SetDlgItemText(hDlg, IDC_CONFESERVER, tfldr2);
+ if(tfldr2)
+ MemFree((void *)tfldr2);
+ }
+
+ if(tfldr)
+ fs_give((void **) &tfldr);
+ }
+ else{
+ LPTSTR local_file;
+
+ local_file = utf8_to_lptstr((LPSTR)dlgcfg->confpath);
+ SetDlgItemText(hDlg, IDC_CONFEFN, local_file);
+ if(!dlgcfg->nopinerc)
+ def_rem_fldr = 0;
+
+ fs_give((void **) &local_file);
+ }
+ }
+ CheckRadioButton (hDlg, IDC_CONFRRADIO, IDC_CONFLRADIO,
+ def_rem_fldr ? IDC_CONFRRADIO : IDC_CONFLRADIO);
+ if(def_rem_fldr){
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFFNTXT), 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFEFN), 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFBROWSE), 0);
+ if(!def_diff_fldr){
+ CheckDlgButton(hDlg, IDC_CONFDFLTFLDR, BST_CHECKED);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 0);
+ }
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 0);
+ }
+ else {
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFSRVRTXT), 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFESERVER), 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFUNTXT), 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFEUSERNAME), 0);
+ CheckDlgButton(hDlg, IDC_CONFDFLTFLDR, BST_CHECKED);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFDFLTFLDR), 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 0);
+ }
+ if(ps_global->install_flag)
+ CheckDlgButton(hDlg, IDC_CONFDFLTSET, BST_CHECKED);
+
+ return (1);
+
+
+ case WM_COMMAND:
+ dlgcfg = (DLG_CONFIGDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
+ switch (wParam) {
+ case IDC_CONFDFLTFLDR:
+ checked = (IsDlgButtonChecked(hDlg, IDC_CONFDFLTFLDR) == BST_CHECKED);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), checked ? 0 : 1);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), checked ? 0 : 1);
+ if(checked)
+ SetDlgItemText(hDlg, IDC_CONFEFLDRNAME, TEXT("remote_pinerc"));
+ break;
+ case IDC_CONFRRADIO:
+ case IDC_CONFLRADIO:
+ CheckRadioButton (hDlg, IDC_CONFRRADIO, IDC_CONFLRADIO, wParam);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFFNTXT), wParam == IDC_CONFRRADIO ? 0 : 1);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFEFN), wParam == IDC_CONFRRADIO ? 0 : 1);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFBROWSE), wParam == IDC_CONFRRADIO ? 0 : 1);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFSRVRTXT), wParam == IDC_CONFRRADIO ? 1 : 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFESERVER), wParam == IDC_CONFRRADIO ? 1 : 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFUNTXT), wParam == IDC_CONFRRADIO ? 1 : 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFEUSERNAME), wParam == IDC_CONFRRADIO ? 1 : 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFDFLTFLDR), wParam == IDC_CONFRRADIO ? 1 : 0);
+ if(wParam == IDC_CONFRRADIO && IsDlgButtonChecked(hDlg, IDC_CONFDFLTFLDR) == BST_UNCHECKED){
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 1);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 1);
+ }
+ else if(wParam == IDC_CONFLRADIO){
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 0);
+ }
+ break;
+ case IDC_CONFBROWSE:
+ if(1){
+ TCHAR fn[MAXPATH+1];
+ OPENFILENAME ofn;
+
+ fn[0] = '\0';
+
+ /* Set up the BIG STRUCTURE. see mswin.c */
+ memset (&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hDlg;
+ ofn.lpstrFilter = NULL;
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = fn;
+ ofn.nMaxFile = MAXPATH;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.lpstrTitle = TEXT("Select File");
+ ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
+ ofn.lpstrDefExt = NULL;
+
+ if (GetOpenFileName (&ofn)) {
+ SetDlgItemText(hDlg, IDC_CONFEFN, fn);
+ }
+ }
+ break;
+ case IDOK:
+ /* Retrieve the new username/passwd. */
+ if(IsDlgButtonChecked(hDlg, IDC_CONFDFLTSET) == BST_CHECKED)
+ dlgcfg->setreg = 1;
+ else
+ dlgcfg->setreg = 0;
+ if(IsDlgButtonChecked(hDlg, IDC_CONFRRADIO) == BST_CHECKED){
+ TCHAR lptstr_buf[MAXPATH+1];
+ char *utf8_srvr, *utf8_username, *utf8_fldrname;
+
+ GetDlgItemText(hDlg, IDC_CONFESERVER, lptstr_buf, MAXPATH);
+ lptstr_buf[MAXPATH] = '\0';
+ utf8_srvr = lptstr_to_utf8(lptstr_buf);
+ removing_leading_and_trailing_white_space(utf8_srvr);
+ if(!*utf8_srvr){
+ MessageBox(hDlg, TEXT("IMAP Server field empty"),
+ TEXT("Alpine"), MB_ICONWARNING | MB_OK);
+ if(utf8_srvr)
+ fs_give((void **) &utf8_srvr);
+
+ return(TRUE);
+ }
+
+ GetDlgItemText(hDlg, IDC_CONFEUSERNAME, lptstr_buf, MAXPATH);
+ lptstr_buf[MAXPATH] = '\0';
+ utf8_username = lptstr_to_utf8(lptstr_buf);
+ removing_leading_and_trailing_white_space(utf8_username);
+ if(IsDlgButtonChecked(hDlg, IDC_CONFDFLTFLDR) == BST_CHECKED){
+ utf8_fldrname = cpystr("remote_pinerc");
+ }
+ else{
+ GetDlgItemText(hDlg, IDC_CONFEFLDRNAME, lptstr_buf, MAXPATH);
+ lptstr_buf[MAXPATH] = '\0';
+ utf8_fldrname = lptstr_to_utf8(lptstr_buf);
+ removing_leading_and_trailing_white_space(utf8_fldrname);
+ if(!*utf8_fldrname){
+ MessageBox(hDlg, TEXT("Configuration Folder Name field empty"),
+ TEXT("Alpine"), MB_ICONWARNING | MB_OK);
+ if(utf8_srvr)
+ fs_give((void **) &utf8_srvr);
+
+ if(utf8_username)
+ fs_give((void **) &utf8_username);
+
+ if(utf8_fldrname)
+ fs_give((void **) &utf8_fldrname);
+
+ return(TRUE);
+ }
+ }
+ if((strlen(utf8_srvr)
+ + strlen(utf8_username)
+ + strlen(utf8_fldrname)
+ + 11) > dlgcfg->confpathlen){
+ MessageBox(hDlg, TEXT("Config path too long"),
+ TEXT("Alpine"), MB_ICONWARNING | MB_OK);
+ if(utf8_srvr)
+ fs_give((void **) &utf8_srvr);
+
+ if(utf8_username)
+ fs_give((void **) &utf8_username);
+
+ if(utf8_fldrname)
+ fs_give((void **) &utf8_fldrname);
+
+ return(TRUE);
+ }
+
+ snprintf(dlgcfg->confpath, dlgcfg->confpathlen, "{%s%s%s}%s", utf8_srvr,
+ *utf8_username ? "/user=" : "",
+ utf8_username, utf8_fldrname);
+ if(utf8_srvr)
+ fs_give((void **) &utf8_srvr);
+
+ if(utf8_username)
+ fs_give((void **) &utf8_username);
+
+ if(utf8_fldrname)
+ fs_give((void **) &utf8_fldrname);
+ }
+ else{
+ TCHAR lptstr_fn[MAXPATH+1];
+ char *utf8_fn;
+
+ GetDlgItemText(hDlg, IDC_CONFEFN, lptstr_fn, MAXPATH);
+ lptstr_fn[MAXPATH] = '\0';
+ utf8_fn = lptstr_to_utf8(lptstr_fn);
+ removing_leading_and_trailing_white_space(utf8_fn);
+ if(!*utf8_fn){
+ MessageBox(hDlg, TEXT("Configuration File Name field empty"),
+ TEXT("Alpine"), MB_ICONWARNING | MB_OK);
+ if(utf8_fn)
+ fs_give((void **) &utf8_fn);
+
+ return(TRUE);
+ }
+
+ if(strlen(utf8_fn) >= dlgcfg->confpathlen){
+ MessageBox(hDlg, TEXT("Config path too long"),
+ TEXT("Alpine"), MB_ICONWARNING | MB_OK);
+ if(utf8_fn)
+ fs_give((void **) &utf8_fn);
+
+ return(TRUE);
+ }
+
+ strncpy(dlgcfg->confpath, utf8_fn, dlgcfg->confpathlen);
+ dlgcfg->confpath[dlgcfg->confpathlen-1] = '\0';
+ if(utf8_fn)
+ fs_give((void **) &utf8_fn);
+ }
+
+ EndDialog (hDlg, LOWORD(wParam));
+ dlgcfg->rv = 0;
+ ret = TRUE;
+ break;
+
+ case IDCANCEL:
+ dlgcfg->rv = 1;
+ ret = TRUE;
+ EndDialog (hDlg, LOWORD(wParam));
+ break;
+ }
+ break;
+
+
+ }
+ return (ret);
+}
+
+/*
+ * Get a button position in the parent's coordinate space.
+ */
+static void
+GetBtnPos (HWND hPrnt, HWND hWnd, RECT *r)
+{
+ GetWindowRect (hWnd, r);
+ ScreenToClient (hPrnt, (POINT *) r);
+ ScreenToClient (hPrnt, (POINT *) &r->right);
+}
diff --git a/alpine/osdep/termout.wnt.h b/alpine/osdep/termout.wnt.h
new file mode 100644
index 00000000..35ccbb77
--- /dev/null
+++ b/alpine/osdep/termout.wnt.h
@@ -0,0 +1,47 @@
+/*
+ * $Id: termout.unx.h 159 2006-10-02 22:00:13Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PINE_OSDEP_TERMOUT_WNT_INCLUDED
+#define PINE_OSDEP_TERMOUT_WNT_INCLUDED
+
+#include "resource.h"
+
+typedef struct DLG_SORTPARAM {
+ int rval; /* Return value. */
+ int reverse; /* Indicates a reversed sort. */
+ int cursort; /* Current sort (pineid). */
+ char **helptext; /* Pointer to help text. */
+ int sortcount; /* Number of different sorts. */
+ struct sorttypemap *types; /* Pointer to array of conversion between
+ * the pine sort types and the radio button
+ * ids. */
+} DLG_SORTPARAM;
+
+
+/* exported prototypes */
+
+void scroll_setpos(long);
+void scroll_setrange(long, long);
+
+/* dialog stuff */
+int init_install_get_vars(void);
+int os_argsdialog(char **);
+int os_login_dialog(NETMBX *, char *, int, char *, int, int, int, int *);
+int os_flagmsgdialog(struct flag_table *);
+int os_sortdialog(DLG_SORTPARAM *);
+int os_config_dialog(char *, int, int *, int);
+
+#endif /* PINE_OSDEP_TERMOUT_WNT_INCLUDED */
diff --git a/alpine/osdep/windlg.h b/alpine/osdep/windlg.h
new file mode 100644
index 00000000..7730ae88
--- /dev/null
+++ b/alpine/osdep/windlg.h
@@ -0,0 +1,10 @@
+
+
+/*----------------------------------------------------------------------------
+
+ Common includes for custom dialogs.
+
+ ( This file included by os-win.h and os-wnt.h)
+
+*/
+