diff options
author | Eduardo Chappa <echappa@gmx.com> | 2013-02-03 00:59:38 -0700 |
---|---|---|
committer | Eduardo Chappa <echappa@gmx.com> | 2013-02-03 00:59:38 -0700 |
commit | 094ca96844842928810f14844413109fc6cdd890 (patch) | |
tree | e60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /alpine/osdep | |
download | alpine-094ca96844842928810f14844413109fc6cdd890.tar.xz |
Initial Alpine Version
Diffstat (limited to 'alpine/osdep')
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 Binary files differnew file mode 100644 index 00000000..0bd797be --- /dev/null +++ b/alpine/osdep/alpine-splash.bmp diff --git a/alpine/osdep/alpine.ico b/alpine/osdep/alpine.ico Binary files differnew file mode 100644 index 00000000..d6b7af76 --- /dev/null +++ b/alpine/osdep/alpine.ico 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 *)"ax, 0, sizeof(struct dqblk)); + if(quota(Q_GETDLIM, getuid(), statx.st_dev, "ax) < 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 Binary files differnew file mode 100644 index 00000000..0c6306b3 --- /dev/null +++ b/alpine/osdep/mclosed.ico 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 Binary files differnew file mode 100644 index 00000000..47783cb8 --- /dev/null +++ b/alpine/osdep/newmail.ico 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 *)"ax) < 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 *)"ax) < 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) + +*/ + |